UI Customization

Almost all of the UI generated by Mavo is customizable. Find out how in this section.

Styling with CSS

The easiest way to customize the UI is via CSS. You can find many style hooks in the index.

Some examples for common cases follow:

Style differently in edit mode

Give an element with property="foo" a yellow background when it is in edit mode:

		[property="foo"][mv-mode="edit"] {
			background: yellow;

Show something only to logged in users

mv-permissions is an attribute set by Mavo on the Mavo root containing a space-separated list of available permissions. When a Mavo allows login but the current user is not logged in, mv-permissions will include the value login. You can use this in your CSS to style things differently based on whether the current user is logged in.

For example, let's say you have an auth class and you want to only show anything with that class to authenticated users. You can do this with this CSS:

		[mv-permissions~="login"] .auth {
			display: none;

Note the ~= in the attribute selector above. This allows you to match for one value in a space-separated list, instead of the entire attribute.

For convenience, there are also mv-logged-in and mv-logged-out classes that you can use on your HTML to show things only to logged in or logged out users respectively.

Mavo toolbar

The Mavo toolbar is the dark toolbar that you get by default on every Mavo app, with controls like Edit, Save, Clear etc. By default it is added inside the Mavo root, at the beginning.

The mv-bar attribute: Remove buttons, enable optional buttons, change order, hide the toolbar

The mv-bar attribute controls which buttons are going to appear, if any. It’s typically specified on the Mavo root. Buttons are represented by their ids. You can find the ids of the built-in buttons below, but keep in mind that Plugins may add more:
id Default? Button
status Displays currently logged in info for backends that support login
edit Edit button
save Save button
import Upload a JSON file and override current data.
export Download current data as a JSON file.
login Login button
logout Logout button

Just including a series of ids in the mv-bar attribute restricts the toolbar to these buttons, in that order.

However, often we only want to add or remove a few buttons to the default set. With the syntax above, we would need to remember all default ids and their default order in order to specify the buttons we want. This is why mv-bar also supports a relative syntax: by starting the value with with all values are interpreted as relative to the default set of buttons. You can then remove buttons by using a no- prefix and add buttons by just specifying their ids.

Note that the edit button is still there, even though we didn't have to explicitly specify it.

The with keyword can be omitted if there’s at least one no-*.

Want to hide the Mavo bar from logged out users? Use mv-bar="no-login". You can still log in without a Mavo toolbar, by adding ?login to the page URL. Note that browsers often block popups more aggressively when they are not triggered by a click so you may need to manually approve the authentication popup when using this.

Hide the toolbar completely

Use mv-bar="none". You can then use classes like mv-status, mv-edit, mv-save, mv-clear, mv-login, mv-logout etc on your own buttons to provide the corresponding functionality. However, note that if you choose to go this route, these buttons will be always shown, regardless of whether the user has permission for the corresponding action. You can use an mv-permissions attribute selector to fix this.

Change its placement and/or use your own HTML element for it

Just use class="mv-bar mv-ui" on your desired element.

Remove default styling

Follow the process above for using a custom toolbar element, and omit the mv-ui class:

This is useful when you want a completely different styling and would rather start from a blank state. You can see a real example of custom toolbar styling on the SVG Paths demo.

Custom button elements

Follow the process above for using a custom toolbar element, and include your custom button inside it with the appropriate mv-BUTTON_ID class. For example, to have a Save button with the text "Store" instead of "Save", you could do:

Item controls

These are the buttons that Mavo adds to each collection item for deleting it, moving it, or adding items before/after it. By default they are added as the last child of the collection item.

To change the placement of their container and/or use your own HTML element for it, just use class="mv-item-bar mv-ui" on your desired element. Note that if you have nested collections, this will be associated with the collection that is the closest ancestor of the element.

Similarly to the Mavo toolbar, if you don’t want any of the default styling associated with these controls just omit the mv-ui class.

Add new item button

For every collection, a button to add new items is generated and placed before the collection if it has mv-order="desc" or after it otherwise. The default label of the button is of the form "Add [name]", where [name] is the name of your collection.

Often you may want a custom label or a custom placement for this button. You can do this by using a class of mv-add-[name] on your desired element, where [name] is the name of the collection you wish to associate it with. Alternatively, if the association is obvious, you can just use a class of mv-add instead.

Both of these classes are also present on the generated buttons and you can use them for styling.

Customizing Text & Localization

Your app needs to be in a different language? No problem! You can customize every bit of displayed text, whether that is to change the text displayed to your liking or to localize it to a different language.


First check the available locale plugins in case your language is available. If not, you would have to write one yourself, using the methods outlined below.

Customizing text via HTML

You can use a <datalist> element to define your own phrases or localize text. The syntax is:

Please note that the lang attribute is mandatory, even if you’re only overriding a few English phrases. Please note that lang is not a Mavo attribute, it’s an HTML attribute and its values are described in any HTML documentation.

Please try to avoid locales with hyphens unless you absolutely need to. E.g. it's better to define a general French (lang="fr") locale and another Canadian French (Québécois) locale (lang="fr-ca") with only the phrases that are different. The reason is that any French dialect can fall back to general French, but not to a specific dialect of French, which means that even if you have defined a locale for fr-ca, apps with lang="fr" will be displayed in English.

Please note that this datalist element is static, i.e. changes to its contents via scripts or expressions will not be picked up.

For a list of ids and phrases that you can copy as a starting point, use src/locale.en.js, however note that plugins can also define their own phrases.

Customizing text via JavaScript

You can write your own localization plugin, by using Mavo.Locale.register(languageCode, phrases). For an example, you can look at the Greek localization plugin.

If you go that route, please consider adding your plugin to the Plugins directory so that others can benefit too! Don’t worry if it's not perfect, others can improve it via pull requests!