Styling components
This is an experimental solution
The pattern behind styling components dynamically from within the CMS is still being researched. The proposed solution might change based on user feedback.
Vue Storefront integration for Bloomreach Content not only allows you to add components to your pages. It also offers a pattern for styling these components dynamically from within the CMS.
It all starts with the Styles field group defined in Bloomreach Content. It allows you to modify your components' CSS, including:
- margins,
- paddings,
- height,
- width,
- flex container properties,
- grid container properties.
Each of these property groups is represented by a separate field group in Bloomreach Content (e.g Margins, Paddings or Grid container properties). The Styles field group is simply bringing them all together. Finally, all document types implement the Styles field group. As a result, you can add stylesheets to our components from within the Experience Manager.
Flexible screen resolutions
You can create different stylesheets for different screen resolutions. All you have to do is specify min
and max
properties under Screen resolution. For screens bigger than 600
pixels and smaller than 1200
pixels:
If you omit the min
and max
properties, the stylesheet will be applied to all screen resolutions unless overriden by other stylesheets which do have min
and max
set.
Multiple CSS properties
The styles
property which lands on the frontend is an array of stylesheet objects. Once the RenderComponent
wrapper gets the CMS component data, it locates the styles
array and transforms it into a set of <style />
tags added to the <head />
of the current document. Each <style />
tag uses media queries and is tied to a specific frontend component through a unique CSS class.
<style>
@media (min-width: 600px) and (max-width: 1200px) {
.cms-component-19515447-5126-41ec-ab74-57a11f5d0c4c {
/* component styles go here */
}
}
</style>
The logic inside RenderComponent
traverses objects within the styles
array and looks for properties with primivite values. Once found, they are transformed into CSS declarations. For example, the following object found in the styles
array:
{
resolutions: {
min: 600,
max: 1200
},
margins: {
margin_top: '30px',
margin_bottom: '30px',
margin_left: 'auto',
margin_right: 'auto',
},
dimensions: {
width: '300px'
}
}
would be transformed into the following <style />
tag:
<style>
@media (min-width: 600px) and (max-width: 1200px) {
.cms-component-19515447-5126-41ec-ab74-57a11f5d0c4c {
margin-top: '30px';
margin-bottom: '30px';
margin-left: 'auto';
margin-right: 'auto';
width: '300px';
}
}
</style>
Proper casing is required!
Names of objects containing the primitives do not matter. What matters is the casing of multi-word CSS property names (e.g. margin-top
). By convention, they must use snake_case so that the RenderComponent wrapper can transform them properly. Bear that in mind while augmenting the styles
field group with your custom CSS properties.
Hero slider example
Dynamic styles are especially useful for components which are nested inside other components. A perfect example might be a Hero slider built from the Hero and the Scrollable.
By default, Storefront UI Scrollable component inserts a vertical gap between all of its elements. What might be desirable for a product card slider, does not look good in case of a Hero slider which should always span the entire width of the screen.
Fortunately, we can change that using the Gaps property. Set it to 0
and the ugly vertical gap on the left disappears:
Caveats
Being an experimental solution, the pattern behind styling components dynamically has certain limitations.
Classes do not affect nested components
Classes generated as a result of the styles
transformation are only applied to the root elements of page components. They cannot affect deeply nested elements such as buttons or images. Fortunately, the default implementation should give you enough flexibility in the vast majority of cases.
Unnecessary properties in certain components
A single Styles field group shared between all components might not be the best solution. It contains a lot of properties. Some of them are universal and applicable to all components (e.g. margin
or padding
) whereas other are rather component-specific (e.g. grid-template-areas
). It would be advisable to create a dedicated field group for every component, containing the relevant properties only.
As soon as the solution is not experimental anymore (i.e. receives proper feedback on the ease of use and the choice of CSS properties for every component), such separate field groups for all components will be delivered as part of the integration. Until then, we strongly encourage you to reuse the existing field groups for CSS properties (e.g. Margins, Paddings, Gaps) and create your custom styling field groups for components.