Theme Styles

In the theme editor there are three tabs: "Settings", "Styles", and "Palettes".

The theme styles are under the "Styles" tabs and they are intended to be style fields to allow someone to edit the look of the website.

There is no function difference between the theme settings and the styles tab. Convention, though, is to organize setting and configuration type fields under the Settings tab and style fields under the Styles tab.

Some example uses of theme styles include:

  • Allow someone to edit the fonts and typography of their website.
  • Enable someone to edit colors for different sections of the website.
  • Editing the margins and paddings of elements.

As the website designer/developer, you have full control over the fields and how they are organized. 

The biggest difference between the Aptuitiv theme editor and other website builders is that the developer controls what styles or settings are available. By default nothing is editable. You can set up and organize the styles that you want to expose.

Displaying theme styles in your website

Theme settings and styles are global variables, which means that they are made available to all templates.

Just like theme settings, theme styles are accessed under the _core.theme.settings variable. This is useful if you need to do include some additional logic to output styles or you want to inline the styles on an HTML tag.

More commonly, though, is to include the theme styles as inline CSS that is automatically output in the <head> section of the page. This is done by including the {{ _page.themeStyles() }} tag in the <head> section of your site templates. The {{ _page.themeStyles() }} tag outputs a <style> tag containing all of the CSS values for fields that have their render configuration set to css-head.

The inline CSS that is generated for the site templates uses the same configuration that the theme preview does. The only differences are that similar CSS selectors are combined together, and, if a Google font is set with the Font Family field type, then a <link> tag is generated to include each Google font.

Saved theme styles are also used within the rich text editor so that when you edit your content you can see the content with the theme styles.

In order to generate the CSS you have to configure the render value for a field.

  • You need to set the render type to css-head.
  • You must set one of the following CSS configuration values:
    • cssSelector
    • cssVariable
  • If you set the cssSelector, you may also need to set the cssProperty value. Some field types automatically handle this, but others, like the size field type do not because they can be used in a variety of ways.

If a field does not have a value then no CSS is output or saved.

Before July 31, 2024 preview was used for the render configuration instead of render. It is still supported, but render is the recommended value to use.

The following render configurations are used with theme styles.

  • cssSelector The name of the CSS selector to output with the field value.
  • cssProperty The name of the CSS property to output with the field value.
  • cssVariable. The name of the CSS variable to output with the field value.
  • mediaQuery The CSS media query to apply the style under.
  • state The element state to apply the style to. This is used if type is css-head. Allowed values include active, focus, and hover.
  • template The template for the field value if you need to alter it before outputting the value.
  • type (required) This specifies how the field value will be previewed and output. You would set it to css-head to output as CSS.

Here is an example using a margin field type and outputting a CSS variable.

{
    "name": "accordionHeadingMargin",
    "label": "Margin",
    "type": "margin",
    "defaultValue": "10px 0",
    "render": {
        "type": "css-head",
        "cssVariable": "--Accordion-heading-margin"
    }
},

There are three ways to output css.

  1. Use a CSS selector
  2. Use a CSS variable
  3. Use a template

Use a CSS selector

If you use a CSS selector then something like this will get output:

.mySelector {font-size: 2.2rem}

Set just the CSS selector

Some field types automatically set the CSS property that is used when outputting the CSS. This includes:

  • borderRadius
  • boxShadow
  • fontFamily
  • fontSize
  • fontWeight
  • letterSpacing
  • lineHeight
  • margin
  • padding
  • textShadow

If you're using one of those field types then you don't need to set the cssProperty value. You only need to use the cssSelector value.

{
    "name": "headingLetterSpacing",
    "label": "Heading letter spacing",
    "type": "letterSpacing",
    "render": {
        "type": "css-head",
        "cssSelector": ".TextHeading"
    }
},

This will output something like this: 

.TextHeading {letter-spacing: 3px}

Set the CSS selector and property values

If you're not using a field type that automatically sets the cssProperty value then you will need to set it.

You can also override the cssProperty value that a field sets.

Here is an example using the color field type to set the text color.

{
    "name": "headingColor",
    "label": "Heading color",
    "type": "color",
    "render": {
        "type": "css-head",
        "cssSelector": ".TextHeading",
        "cssProperty": "color"
    }
},

This will output something like this:

.TextHeading {color: #ffffff}

Here is an example of using the size field type to set the left margin of an element.

{
    "name": "blockLeftMargin",
    "label": "Left margin",
    "type": "size",
    "render": {
        "type": "css-head",
        "cssSelector": ".someBlock",
        "cssProperty": "margin-left"
    }
},

Set the CSS selector, property, and a template

If you need more control over the CSS value that is output then you can also use the template value.

Here is an example where the size field type is used to output the font size. It's configured to only show "px" as the unit type because that's often more familiar to non-designers. But, the developer wants the CSS to be output in rems. (In their CSS they style the body font so that 1rem is the same as 10px.) Logic is used in this example to only output a value if the field is set (The size field's unit is always set, but the size value isn't.)

{
    "name": "elementFontSize",
    "label": "Font size",
    "type": "fontSize",
    "defaultValue": "18px",
    "allowedUnits": ["px"],
    "render": {
        "type": "css-head",
        "cssSelector": ".myElement",
        "cssProperty": "font-size",
        "template": "{% if value.size %}{{ value.size / 10 }}rem{% endif %}"
    }
}

This will output something like this if the field has a value:

.myElement {font-size: 1.2rem}

Set the CSS selector and a template

You typically only do this with field types that don't define the cssProperty. In this scenario your template value would include the CSS property value.

We'll use the same font size example as above but alter the template value to output the font-size property.

{
    "name": "elementFontSize",
    "label": "Font size",
    "type": "fontSize",
    "defaultValue": "18px",
    "allowedUnits": ["px"],
    "render": {
        "type": "css-head",
        "cssSelector": ".myElement",
        "template": "{% if value.size %}font-size: {{ value.size / 10 }}rem{% endif %}"
    }
}

Use a CSS variable

Instead of outputting a CSS selector and it's styles you can output a CSS variable and it's value.

If you use a CSS variable then something like this will get output:

:root {
   --myVariable: 10px;
}

You would then use the CSS variable within your CSS files.

There are a couple of different ways to set the value for a CSS variable.

Set just the CSS variable

If the field type outputs the value in the exact format that you need then you only need to configure the cssVariable value.

For example, you can use the size field type and set the border size for an image.

{       
    "name": "imageBorderSize",
    "label": "Image border size",
    "type": "size",
    "defaultValue": "2px",
    "render": {
        "type": "css-head",
        "cssVariable": "--Image-border-size"
    }
}

Set the CSS variable and a template

If you need more control over the value for the CSS variable then you can also set the template value. The template value will be used to generate the value that is output with the CSS variable.

Here is an example of using a switch field type to set the display of an element.

{
    "name": "formRequiredShowAsterisk",
    "label": "Show the \"*\" next to the field label for required fields",
    "type": "switch",
    "defaultValue": "yes",
    "render": {
        "type": "css-head",
        "cssVariable": "--FormRequiredMessage-asterisk-display",
        "template": "{{ value == 'yes' ? 'inline' : 'none' }}"
    }
}

Here is an example of using the stepper field type to output a pixel value.

{
    "name": "buttonPaddingHorizontal",
    "label": "Horizontal padding",
    "type": "stepper",
    "after": "px",
    "defaultValue": "20",
    "render": {
        "type": "css-head",
        "cssVariable": "--Button-padding-horizontal",
        "template": "{{ value }}px"
    }
}

Use a template

If you need full control over the CSS output, then you can use just the template value.

If the field does not have a value, then the template is not rendered and no CSS will be output or saved for that field.

The Twig rendering engine is sensitive to curly brackets. Don't place Twig tags or variables right after the curly brackets for a CSS declaration. They will be interpreted as variables. Put a space after and before the CSS declaration curly brackets.

{# Don't do this #}
"template": ".Accordion-heading {{% if value == 'before' %} justify-content: flex-end; flex-direction: row-reverse;{% else %} justify-content: {{ value }};{% endif %}}"

{# Do this: place a space after the opening { and before the closing } for the CSS #}
"template": ".Accordion-heading { {% if value == 'before' %} justify-content: flex-end; flex-direction: row-reverse;{% else %} justify-content: {{ value }};{% endif %} }"

Here is an example of using a ratio field to set two CSS variables that define the height and width styles for an image.

{
    "name": "imageSize",
    "label": "Image size",
    "type": "ratio",
    "after": "px",
    "xLabel": "Width",
    "yLabel": "Height",
    "defaultValue": "30px",
    "render": {
        "type": "css-head",
        "template": ":root {--Element-image-width: {{ value.x }}px; --Element-image-height: {{ value.y }}px;}"
    }
}

Here is an example of using an image upload field to set the background image for an element.

{
    "name": "backgroundImage",
    "label": "Background image",
    "type": "image",
    "useAttributes": false,
    "render": {
        "type": "css-head",
        "template": ".myElement {background-image: url('{{ value.url }}');}"
    }
}

Here is an example of setting some additional CSS with the field's CSS output.

{
    "name": "showTheContent",
    "label": "Show the overlay image",
    "type": "switch",
    "defaultValue": "none",
    "valueOn": "block",
    "valueOff": "none",
    "render": {
        "type": "css-head",
        "template": ".Content-overlay {display: {{ value }};} {% if value == 'none' %} .Content {padding-bottom: 0 !important;} {% endif %}"
    }
}

Here is an example of outputting a custom media query.

{
    "name": "mainNavHideWidth",
    "label": "Hide the navigation on screens smaller than",
    "type": "size",
    "defaultValue": "700px",
    "render": {
        "type": "css-head",
        "template": "{% if value.size %}@media (min-width: {{ value.size }}{{ value.unit }}) { .MainNav {display: flex; } }{% endif %}"
    }
}

CSS Hover, Active, and Focus states

You can scope a CSS render value to a interactivity state. The following interactivity states are supported:

  • hover
  • active
  • focus

When a state value is used it's added to the cssSelector as part of the CSS selector statement.

{
 "label": "Heading text color",
 "name": "headingTextColor",
 "type": "color",
 "render": {
    "type": "css-head",
    "cssSelector": ".TextHeading",
    "state": "hover"
 }
}

The output will be something like this:

.TextHeading:hover {color: #ff0000}

CSS media queries

You can scope a CSS value to a media query if you want. It works with cssSelector and template types. If you use the cssVariable value then the media query is not used.

The mediaQuery value should have the entire valid media query minus the @media portion and any curly brackets.

{
 "label": "Heading text color",
 "name": "headingTextColor",
 "type": "color",
 "render": {
    "type": "css-head",
    "cssSelector": ".TextHeading",
    "mediaQuery": "(min-width: 768px)"
  }
}
This documentation is only for Aptuitiv CMS. Learn more.
Get Started With Aptuitiv