Hyvä CMS Block Styling Conventions with Tailwind CSS
AI generated
</>
tw
Tailwind CSS · Hyvä Theme · Magento · CMS
Hyvä CMS Block Styling Conventions
Safe Tailwind classes for editors

CMS blocks in Magento are edited by content editors in the WYSIWYG, not by developers in phtml files. Without fixed Hyvä CMS block styling conventions, inconsistent layouts appear, along with broken utility classes the Tailwind JIT compiler never generated, and CSP violations from inline styles. A small, documented class set solves this problem for good.

17 min read Tailwind CSS v4 · Hyvä CSP Theme Magento CMS · Editor Workflow

1. Why CMS blocks need their own class system

Static phtml templates are written by developers, checked against the Tailwind configuration, and built before deployment. CMS blocks, in contrast, live as HTML in the database and are edited by content editors in the WYSIWYG or directly in source code mode. This is exactly where the problem for Hyvä CMS block styling begins: an editor can type any Tailwind class into the editor, but the Tailwind JIT compiler only generates CSS for classes it actually finds in the configured files at build time.

Without clear conventions for Hyvä CMS block styling, a patchwork quickly emerges: one editor uses bg-blue-600, another uses bg-sky-500, a third copies an old class from a Word document that does not even exist in Tailwind. The result is blocks that look fine in the editor but stay unstyled on the live shop, because the corresponding CSS is missing from the build. The following sections show how to solve this problem structurally instead of reactively.

The framing matters: CMS content in Magento is typically stored as free text and rendered through \Magento\Cms\Model\Template\FilterProvider, with widget directives like {{widget type="Magento\\Cms\\Block\\Block" block_id="..."}}. This rendering has nothing to do with the Tailwind build, the CSS must already exist independently of it before the editor saves the block.

2. The content scanning problem: Tailwind cannot see a database

Tailwind CSS v4 scans the files specified in the @source directory or the configuration for class names and only generates actual CSS for the matches it finds. Database content, such as CMS block content, does not belong to these sources by default. This is the core of the problem in Hyvä CMS block styling: even a syntactically correct Tailwind class that only exists in the database produces no CSS if it never appears anywhere in the scanned source code.

One solution is a periodic export of all CMS block and CMS page content into a single text file that is additionally registered as a Tailwind source. This works but is fragile, because it requires an extra build step and is easily forgotten when an editor uses a new class after the last export. A more robust approach is the one from section 3: a fixed, pre built class set that is guaranteed to land in the CSS bundle regardless of the actual CMS content.


// tailwind.config.js — include exported CMS content as an additional source
// Regenerate cms-content-dump.html via a cron job or deploy hook
export default {
  content: [
    './app/design/frontend/Vendor/theme/**/*.phtml',
    './app/design/frontend/Vendor/theme/web/js/**/*.js',
    // Fallback source: exported CMS block/page HTML for JIT scanning
    './var/tailwind/cms-content-dump.html'
  ]
};

3. Defining a fixed class set for editors

The most robust approach for Hyvä CMS block styling is not to give editors raw Tailwind utilities at all, but a small set of semantic component classes defined through @layer components. Instead of class="bg-sky-600 text-white font-bold py-3 px-6 rounded-xl", the editor simply types class="cms-btn". This class is guaranteed to exist in the CSS bundle, because it is defined in a real phtml or CSS file and therefore picked up by the build, regardless of the database content.

This pattern drastically reduces the error rate: there are no more misspelled color values, no inconsistent spacing between different editors, and no classes that simply do not exist. For Hyvä CMS block styling this means developers define the vocabulary once, editors combine it freely, and the visual consistency of the entire shop is preserved, all without editors having to understand Tailwind itself.


/* app/design/frontend/Vendor/theme/web/tailwind/tailwind-source.css */
@layer components {
  .cms-btn {
    @apply inline-flex items-center justify-center bg-sky-600 text-white font-bold
           py-3 px-6 rounded-xl hover:bg-sky-700 transition-colors;
  }
  .cms-btn-outline {
    @apply inline-flex items-center justify-center border-2 border-sky-600 text-sky-700
           font-bold py-3 px-6 rounded-xl hover:bg-sky-50 transition-colors;
  }
  .cms-grid-2 {
    @apply grid grid-cols-1 md:grid-cols-2 gap-6 my-8;
  }
  .cms-grid-3 {
    @apply grid grid-cols-1 md:grid-cols-3 gap-6 my-8;
  }
  .cms-card {
    @apply rounded-2xl border border-slate-200 p-6 bg-white shadow-sm;
  }
}

4. Safelist instead of free class choice

Some editors still need flexibility, for example different background colors for seasonal campaign blocks. For this limited case, an explicit safelist in the Tailwind configuration is the right solution: a defined, finite list of allowed classes is always included in the CSS bundle regardless of content scanning. This differs fundamentally from fully free access to all Tailwind utilities, because the list is deliberately curated and documented.

What matters for Hyvä CMS block styling is keeping the safelist as small as possible and making it available to editors as a documented selection, for example as a short table in an internal wiki. An uncontrolled safelist growing to hundreds of entries leads to the same CSS bundle size problems as the old Tailwind v2 without a JIT compiler, and defeats the actual purpose of the utility first approach.


// tailwind.config.js — curated safelist for seasonal campaign blocks
export default {
  safelist: [
    'bg-sky-600', 'bg-rose-600', 'bg-amber-600', 'bg-emerald-600',
    'text-sky-700', 'text-rose-700', 'text-amber-700', 'text-emerald-700',
    { pattern: /^(bg|text)-(sky|rose|amber|emerald)-(50|100)$/ }
  ]
};

5. Block variants through data attributes

For more complex block variants, for example a hero section with centered versus left aligned text, a data-block-variant attribute is more robust than multiple Tailwind classes in the CMS content. The editor selects a documented value like data-block-variant="hero-centered" in source code mode, while the entire visual behaviour is defined through CSS attribute selectors in the theme. This reduces the attack surface for Hyvä CMS block styling mistakes to a minimum, because only a few, reviewed values exist.

This approach has another benefit: if the design of a variant changes, only the CSS rule in the theme needs adjusting, not every single CMS block in the database. Across hundreds of blocks spread over multiple store views, that is the decisive difference between a maintainable and an unmaintainable Hyvä CMS block styling strategy.


<!-- CMS block content, entered by an editor in source code mode -->
<div class="cms-hero" data-block-variant="hero-centered">
  <h2>Summer Collection 2026</h2>
  <p>Up to 40 percent off, while stock lasts.</p>
  <a class="cms-btn" href="/sale.html">Discover now</a>
</div>

<!-- Referencing an existing CMS block via widget directive -->
{{widget type="Magento\Cms\Block\Block" block_id="footer_trust_badges"}}

6. CSP compliance: no inline styles in CMS content

The Hyvä CSP theme requires a strict content security policy that blocks inline styles without a nonce by default. Editors tend to add colors and spacing directly as style="color: red;" in the WYSIWYG editor, because the visual editor interface offers that option prominently. For consistent Hyvä CMS block styling, this option must be disabled in the TinyMCE editor, or at least clearly documented as forbidden.

The replacement is exclusively the predefined classes from section 3 and the safelist from section 4. Both paths produce valid, CSP compliant CSS, because they run through the Tailwind build pipeline instead of ending up as inline attributes in the HTML. A once configured TinyMCE style formats dropdown that offers exactly the documented Hyvä CMS block styling classes even makes this path more convenient for editors than free inline styling.

7. Semantics and accessibility in CMS blocks

CMS blocks are often embedded in existing pages, for example as a footer trust badge or a category page description. A common problem: editors use an <h1> heading inside a block in the WYSIWYG, even though the page already has its own <h1>. Clean Hyvä CMS block styling includes a fixed heading convention, typically starting at <h2> inside every CMS block, so the document structure stays consistent across all embedded blocks.

Equally important is the correct role for blocks that act as standalone regions, for example role="region" with aria-label for a newsletter signup block. These semantic attributes can be baked into the same predefined classes from section 3, so editors get them automatically without having to learn ARIA rules themselves.

8. Common mistakes in CMS block styling

The most common mistake is copying Tailwind classes directly from the developer theme into the CMS editor, without checking whether these classes actually exist in the built CSS bundle. Classes like lg:grid-cols-[1fr_380px] with arbitrary values work in a phtml template because they get scanned at build time, but disappear without a trace in CMS content if no additional scanning is set up.

A second mistake is the lack of central documentation for allowed CMS classes. Without this reference, every editor invents their own solutions, and Hyvä CMS block styling slowly drifts apart over months. A third problem is forgetting responsive variants for images inside CMS blocks, for example missing object-cover and aspect-ratio, which leads to distorted images on mobile devices.

9. Approaches to CMS block styling compared

There are several strategies for connecting Tailwind CSS with dynamic CMS content. The table below ranks them by robustness and maintenance effort for Hyvä CMS block styling in practice.

Approach Risk Maintenance effort Recommendation
Free Tailwind classes in the WYSIWYG Missing CSS, typos High Avoid
CMS content dump as scan source Forgotten re export Medium Only as a supplement
Fixed component classes (cms-btn) Very low Low Primary strategy
Curated safelist for exceptions Low, with a small list Low Supplementary for variants

Mironsoft

Hyvä theme development and Magento CMS conventions

Editors who build consistent blocks without developers?

We build documented CMS block class sets for your Hyvä theme, including TinyMCE integration, safelisting and a CSP compliant setup without inline styles.

Class library

Documented set of cms-btn, cms-grid and cms-card components

Editor integration

TinyMCE style formats for editors with no Tailwind knowledge

CSP audit

Review of existing CMS blocks for inline style violations

10. Summary

Consistent Hyvä CMS block styling does not come from policing every single editor, but from a small, documented vocabulary of component classes like cms-btn, cms-grid-2 and cms-card, defined through @layer components. These classes are guaranteed to exist in the CSS bundle, regardless of whether the actual CMS block content was ever picked up by the Tailwind scanner. For edge cases, a curated safelist adds limited flexibility without letting the bundle size grow out of control.

On top of that, a fixed heading convention and avoiding inline styles secure accessibility and CSP compliance for every single block. Once these conventions are established and made visible in the TinyMCE editor, support requests from editors drop drastically, and the visual appearance stays consistent across hundreds of CMS blocks.

Hyvä CMS Block Styling Conventions — The Essentials at a Glance

Component classes

@layer components defines cms-btn, cms-grid-2, cms-card for editors instead of raw utilities.

Safelist for exceptions

A small, curated safelist allows limited color variants without blowing up the CSS bundle size.

CSP compliance

No inline styles in CMS content, only predefined, built classes should be used.

Semantics

Headings consistently start at h2, regions get role and aria-label through the component class.

11. FAQ: Hyvä CMS Block Styling with Tailwind CSS

1Why do some Tailwind classes not work in CMS blocks?
Tailwind only generates CSS for scanned files. Database CMS content is not included by default and stays unstyled without extra measures.
2Most robust solution for Hyvä CMS block styling?
Fixed component classes like cms-btn via @layer components, guaranteed to land in the build regardless of database content.
3When is a safelist a good idea?
For limited exceptions like campaign colors. Keep it small, documented and curated, otherwise the bundle grows uncontrolled.
4How do data-block-variant attributes work?
Editor sets a documented value, the theme controls behaviour through CSS attribute selectors instead of individual utility classes.
5Why are inline styles problematic?
The Hyvä CSP theme blocks inline styles without a nonce. Predefined classes or safelist entries are the compliant alternative.
6Which heading level should CMS blocks use?
Usually h2, since the embedding page already has its own h1. A fixed convention prevents duplicate structures.
7Scan CMS content directly as a Tailwind source?
Possible via periodic export, but fragile, since a forgotten re export leads to missing CSS after content changes.
8How to reference CMS blocks via widget directives?
Via the widget directive with block_id, replaced server side by the referenced block, whose styling follows the same conventions.
9How many component classes to offer?
As few as possible, usually five to ten well documented classes, to avoid overwhelming editors.
10What happens without aspect-ratio on images?
Images distort on mobile screens. aspect-ratio and object-cover should be part of the predefined image class.