Styling

Learn how to style your components.

You can style custom components in two ways:

  1. Define properties in the <script> element and pass them in the <style> and/or <template> tags.
  2. Define CSS in the <style> element and set them in the <template> tag.

You can use JavaScript in the <script> tag, but not the <style> tag.

Style using JavaScript

You can define properties in the <script> tag that you then pass to a <style> or <template> tag to style your content.

Define properties

Properties allow you to thoroughly customize a component. Here we’ll add some text styling.

<script>
  export const config = {
    "label": "My paragraph",
  };
  export const props = Component.defineProps({
    color: {
      section: 'Text',
      label: 'Color',
      schema: Component.props.string().optional(),
      type: 'color',
    },
    'font-size': {
      section: 'Text',
      label: 'Size',
      schema: Component.props.number().default(16),
      type: 'number',
      min: 14,
      max: 30,
    },
    'text-align': {
      section: 'Text',
      label: 'Align',
      schema: Component.props.enum(['left', 'center', 'right']).optional(),
      type: 'toggle',
      options: [
        { label: 'Left', value: 'left', icon: 'format_align_left' },
        { label: 'Center', value: 'center', icon: 'format_align_center' },
        { label: 'Right', value: 'right', icon: 'format_align_right' },
      ],
    }
  });
  const styleObject = {
    color: props.color,
    'font-size': props['font-size'] + 'px',
    'text-align': props['text-align'],
    'line-height': '150%',
  };
</script>
<template>
  <p #set:style="styleObject">
    This is a paragraph
  </p>
</template>

Begin by adding export const props = Component.defineProps({}).

Above, we added three properties: color, font-size and text-align. Each has a number of additional settings. These are all optional, but we recommend you set some of them to help improve the user experience in the visual editor.

  • section - This groups properties together in the main properties menu.
  • label - This sets a more user friendly name for the property.
  • schema - This defines the type of property, validation (e.g number, string, boolean, enum, etc), default value, and whether it's optional. For a deeper look at validation, check out the zod validation library which our validation is built on.
  • type - This defines the UI control that will show in the properties menu. A few examples of this include:
    • number - a number input
    • color - a color picker
    • slider - a range slider
    • select - a select menu, good for long lists of enum items
    • toggle - toggle buttons, good for shorter lists of enum items
    • size - good for defining widths and heights
    • radius - used for border radius
    • box - used to define 4 sided values, good for margin or padding
    • shadow - used to define a box shadow
    • hidden - the property will not be shown in the visual editor menu, but is still usable from the code view
  • min, max - used to set minimum and maximum values of a number
  • options - this is a way to set user-friendly labels for enum properties. When using this, the value must match the enum value. Also, the icons set here are from Google icons.

Create a style object

After you define your properties, you'll create another object to help build the component and pass styles to your message. Here we'll call it the styleObject, but you can name this anything you like. Then, when you add a style attribute to your template, we will automatically pass this Javascript object to output your styles.

  const styleObject = {
    color: props.color,
    'font-size': props['font-size'] + 'px',
    'text-align': props['text-align'],
    'line-height': '150%',
  };

The names on the left are the CSS attributes you want to include, and on the right are the values. If a property is not set, it will have a value of undefined and will not be included in the output code. You can also include hard-coded styles which aren’t included in the props, like line-height in the example above.

Pass properties into the <template> tag

In the example above, we set the style of the paragraph tag: <p #set:style="styleObject">.

Pass properties into the <style> tag

<style> tags support variables defined in your <script> tag. Pass them as CSS values with the set() function.

.button {
	background: set(background); /* quotes are optional when using alpha chararacters */
	color: set('color');
}

If the value you want to access is inside of an object or array, you can use dot notation.

<script>
	const theme = { background: 'blue' }
<script>
<style>
	.button {
		background:	set('theme.background');
	}
</style>

In your template, you'd then pass the CSS variable:

<a style="button"></div>

Style using CSS

Use <style> tags to define CSS for your component then reference them in your <template> tag.

Conditional CSS

You can use all the conditional directives (#if, #else-if, #else) to render CSS.

<style #if="variant === 'primary'">
	.primary-button {
		background: blue;
		color: white;
	}
</style>
<style #else>
	.default-button {
		background: white;
		color: blue;
	}
</style>

Multiple <style> tags

By default, we merge all <style> tags together to avoid bloat. You can change this with the #isolated> attribute.

For example, these two <style> tags will be merged:

Source:

<style>
.a {
	background: blue;
}
</style>
<style>
.b {
	background: red;
}
</style>

Output:

<style>
.a {
	background: blue;
}
.b {
	background: red;
}
</style>

Standalone styles

Sometimes you need to guarantee that a particular <style> tag lives on its own and is not merged with other <style> tags. You can do so by adding the #isolated attribute.

You might want this when sending emails to Gmail. If the <style> element contains any invalid CSS, Gmail will strip the entire block. But if you wrap this CSS in a #isolated block, Gmail will not strip the rest of the CSS.

<style #isolated>
.a {
	background: blue;
}
</style>
<style>
.b {
	background: red;
}
</style>

You can also group styles together by assigning a value to the #isolated attribute. This can prevent people from receiving a half-styled email; when an email client removes a <style> block, it will also remove all styles with the same value. This practice can help reduce code bloat, too.

<style #isolated="outook-web">
[class~="a"] {
	background: blue;
}
</style>
<style #isolated="outook-web">
[class~="outlook-hide"] {
	display: none;
}
</style>
<style>
.b {
	background: red;
}
</style>
<style #isolated="interactive">
input:checked ~ .c {
	background: green;
}
</style>