PHPackages                             shel/critical-css - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. shel/critical-css

ActiveNeos-plugin[Templating &amp; Views](/categories/templating)

shel/critical-css
=================

Allows inlining and optimising styles for components in Neos CMS

3.0.0(10mo ago)102.5k3[1 issues](https://github.com/Sebobo/Shel.CriticalCSS/issues)GPL-3.0-or-laterPHPPHP &gt;=8.2CI passing

Since Nov 6Pushed 10mo ago1 watchersCompare

[ Source](https://github.com/Sebobo/Shel.CriticalCSS)[ Packagist](https://packagist.org/packages/shel/critical-css)[ GitHub Sponsors](https://github.com/sebobo)[ Patreon](https://www.patreon.com/shelzle)[ RSS](/packages/shel-critical-css/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (3)Dependencies (1)Versions (13)Used By (0)

Adding and combining inline styles for critical CSS in Neos CMS
===============================================================

[](#adding-and-combining-inline-styles-for-critical-css-in-neos-cms)

[![Latest Stable Version](https://camo.githubusercontent.com/ec2f910805a2f2d6a72d741ad0c8ac7cdd6cf57e8f86b65718f5a74e7ae95ce3/68747470733a2f2f706f7365722e707567782e6f72672f7368656c2f637269746963616c2d6373732f762f737461626c65)](https://packagist.org/packages/shel/critical-css)[![License](https://camo.githubusercontent.com/ea7dd4d34da6f8257c430605e461bae99a25b3fe218f28f35090f94e6ea9cd4f/68747470733a2f2f706f7365722e707567782e6f72672f7368656c2f637269746963616c2d6373732f6c6963656e7365)](https://packagist.org/packages/shel/critical-css)[![Travis Build Status](https://camo.githubusercontent.com/70b0d6e085a90b33036b1466d8f97d849a7ba72df02a878f2b422d630680e201/68747470733a2f2f7472617669732d63692e6f72672f5365626f626f2f5368656c2e437269746963616c4353532e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/Sebobo/Shel.CriticalCSS)[![StyleCI](https://camo.githubusercontent.com/f35b0430193ae26b1c069df62f400b6c9849aec2f7ea251540c0b2b94b4751c2/68747470733a2f2f7374796c6563692e696f2f7265706f732f3231393737303233302f736869656c643f7374796c653d666c6174)](https://styleci.io/repos/219770230)

This package provides several helpers to allow adding inline styles to Fusion components in Neos CMS and combining them locally or into the head of a html document. The styles are automatically scoped by default and can be defined dynamically like any other Fusion object.

CSS classes are dynamically generated based on the hash of the defined styles.

This allows you to keep styles together with a component in one file and also be able to override them. A good use case for this is to define inline styles for your critical CSS that should be loaded instantly when the site is shown and defer loading other styles that are not needed immediately.

Use cases:

- Define critical CSS that should be available for "above the fold" content.
- Define dynamic CSS variables for themed websites.
- Include CSS with reusable components.
- Have a minimal set of CSS for each individual page.

Supported:

- Scoped styles
- Style nesting
- Global styles with specific selectors
- Automatic style merging into document head via http component
- `@media` and `@supports` queries

This package doesn't require any specific browser features.

The inspiration for this package came from [SvelteJS](https://svelte.dev) and [JSS](https://cssinjs.org).

Table of contents

- [Installation](#installation)
- [Usage](#usage)
    - [Adding inline styles](#adding-inline-styles)
        - [Nesting styles](#nesting-styles)
        - [Using multiple styles in one component](#using-multiple-styles-in-one-component)
        - [Using the shorthand Fusion helper](#using-the-shorthand-fusion-helper)
        - [Modifying styles with props](#modifying-styles-with-props)
        - [Usage with CSS variables](#usage-with-css-variables)
        - [Custom selectors](#custom-selectors)
        - [Insert styles from a file](#insert-styles-from-a-file)
        - [Other examples](#other-examples)
    - [Modifying the styles collector behaviour](#-modifying-the-styles-collector-behaviour)
        - [Fusion based style collector](#fusion-based-style-collector)
    - [Limitations](#limitations)
        - [Inserting new elements in the Neos UI](#inserting-new-elements-in-the-neos-ui)

Installation
------------

[](#installation)

Run this in your site package:

```
composer require --no-update shel/critical-css

```

Then run `composer update` in your project root.

Usage
-----

[](#usage)

### Adding inline styles

[](#adding-inline-styles)

Given the following example component:

```
prototype(My.Site:Component.Blockquote) < prototype(Neos.Fusion:Component) {
    text = ''

    renderer = afx`
        {props.text}
    `

    @process.styles = Shel.CriticalCSS:Styles {
        font-size = '2em'
        font-family = 'Comic Sans'
        padding = '.5rem'
    }
}

```

The resulting HTML will look similar to this:

```
.style--cd7c679e3d{font-size:2m;font-family:Comic Sans;padding:.5rem;}
My text

```

This will already work but you will have a lot of style tags this way and possible duplicates.

This package automatically applies a "style collector" to the document which collects all these inline styles. So all style tags will first collected, then merged into one list, duplicates removed and inserted into the HTML head as one style tag.

Be careful when applying the styles not only to one tag but to a group of tags. Then it will automatically generate a wrapping tag similar to how the Augmenter in Fusion works.

#### Nesting styles

[](#nesting-styles)

Again a similar example but with nested styles

```
prototype(My.Site:Component.Blockquote) < prototype(Neos.Fusion:Component) {
    text = ''
    link = ''

    renderer = afx`

            {props.text}
            Read more

    `

    @process.styles = Shel.CriticalCSS:Styles {
        font-size = '2em'
        font-family = 'Comic Sans'
        padding = '.5rem'
        a {
            color = 'blue'
            text-decoration = 'underline'
        }
    }
}

```

When nesting you can either use `Neos.Fusion:DataStructure` or simple nesting with braces like in the example.

The resulting HTML will look similar to this:

```
.style--cd7c679e3d{font-size:2m;font-family:Comic Sans;padding:.5rem;}.style--cd7c679e3d a{color:blue;text-decoration:underline;}
My text

```

#### Using multiple styles in one component

[](#using-multiple-styles-in-one-component)

To style several parts of a component you can do the following:

```
prototype(My.Site:Component.Complex) < prototype(Neos.Fusion:Component) {
    headline = ''
    text = ''
    footer = ''

    renderer = afx`

                {props.headline}

            {props.text}

                {props.footer}

    `

    @process.styles = Shel.CriticalCSS:Styles {
        padding = '.5rem'
        div {
            margin = '1rem 0'
        }
    }
}

```

This will result in three style tags with three different css classes. All of them will be picked up by the collector.

#### Using the shorthand Fusion helper

[](#using-the-shorthand-fusion-helper)

Somewhere in your package define the short prototype:

```
prototype(CSS:Style) < prototype(Shel.CriticalCSS:Styles)

```

(Note the needed colon: `CSS`**`:`**`Style`. Fusion doesn't mind, but afx would convert `CssStyle` to a `Neos.Fusion:Tag`. Afx needs a way to differentiate.)

Then you can write the previous example like this:

```
prototype(My.Site:Component.Complex) < prototype(Neos.Fusion:Component) {
    headline = ''
    text = ''
    footer = ''

    renderer = afx`

                {props.headline}

            {props.text}

                {props.footer}

    `

    @process.styles = CSS:Style {
        padding = '.5rem'
        div {
            margin = '1rem 0'
        }
    }
}

```

#### Modifying styles with props

[](#modifying-styles-with-props)

This method allows you to modify styles easily by using props:

```
prototype(My.Site:Component.TextBanner) < prototype(Neos.Fusion:Component) {
    text = ''
    backgroundColor = '#4444ff'

    renderer = afx`

            {props.text}

    `
}

```

Remember you can only access the props when the styles object is applied somewhere inside the `renderer`. You can do this either via `renderer.@process.styles` or like in the example code.

#### Usage with CSS variables

[](#usage-with-css-variables)

You can also easily define global or local CSS variables this way:

```
prototype(My.Site:Document.Page) < prototype(Neos.Neos:Page) {
    body {
        content {
            main = Neos.Neos:PrimaryContent {
                nodePath = 'main'

                @process.styles = Shel.CriticalCSS:Styles {
                    --theme-background = ${q(site).property('themeBackground')}
                    --theme-color = ${q(site).property('themeColor')}
                }
            }
        }
    }
}

```

And when you then have a nested component like this:

```
prototype(My.Site:Component.Blockquote) < prototype(Neos.Fusion:Component) {
    text = ''

    renderer = afx`
        {props.text}
    `

    @process.styles = Shel.CriticalCSS:Styles {
        color = 'var(--theme-color)'
    }
}

```

I can recommend to use my [colorpicker](https://github.com/Sebobo/Shel.Neos.ColorPicker) for Neos CMS when allowing an editor to define a theme and then put those values into CSS variables.

#### Custom selectors

[](#custom-selectors)

It's also possible to use custom selectors to target the `html`, `body` or all tags `*`:

```
prototype(Neos.Neos:Page) {
    body {
        @process.globalStyles = Neos.Fusion:Join {
            all = Shel.CriticalCSS:Styles {
                selector = '*'
                box-sizing = 'border-box'
            }
            body = Shel.CriticalCSS:Styles {
                selector = 'body'
                background-color = 'blue'
            }
        }
    }
}

```

#### Insert styles from a file

[](#insert-styles-from-a-file)

The package has a Fusion helper to insert styles inline from a file. Do scoping is done, but the style tag will be picked up by the style collector.

```
prototype(My.Site:Component.Test) < prototype(Neos.Fusion:Component) {
    text = ''

    renderer = afx`

        {props.text}
    `
}

```

Also works as `process`:

```
prototype(My.Site:Component.Test) < prototype(Neos.Fusion:Component) {
    text = ''

    renderer = afx`
        {props.text}
    `

    @process.addStyles = Shel.CriticalCSS:LoadStyles {
        path="resource://My.Site/Private/Fusion/Components/Test/style.css"
    }
}

```

#### Other examples

[](#other-examples)

You can also take a look at the [functional test fixtures](Tests/Functional/Fixtures/Fusion/Styles.fusion) to see the verified use cases.

### Modifying the styles collector behaviour

[](#modifying-the-styles-collector-behaviour)

By default the collector is applied as http middleware at the end of the request chain. It will merge all inline styles generated with this package into one style tag in the html head. Duplicates are removed during this process. You can disable this behaviour with this setting:

```
Shel:
    CriticalCSS:
        mergeStyles:
            enabled: false

```

#### Fusion based style collector

[](#fusion-based-style-collector)

This package contains a second collection method via Fusion. The `Shel.CriticalCSS:StyleCollector` helper can be used in a similar way as `process` to merge all inline style tags into one. When doing this inside the DOM the style tag will be prepended wherever it is applied to. When applying it to the whole document, it will also merge the styles into the html head.

This method can be helpful in certain cases but has issues when the contained components have their own cache configurations. This is why the http component is preferred to solve this on the document level. But if for some reason you cannot use the default, this might help.

### Limitations

[](#limitations)

#### Inserting new elements in the Neos UI

[](#inserting-new-elements-in-the-neos-ui)

When working the backend the styles collector will not automatically pick up style blocks from newly inserted elements. This might cause some issues when the added elements are somehow treated with Javascript like in Sliders.

#### Caching

[](#caching)

As explained in the styles collector section, the Fusion based collector has issues with cached components that have styles applied to them. This can result in styles missing from the document.

###  Health Score

46

—

FairBetter than 93% of packages

Maintenance51

Moderate activity, may be stable

Popularity27

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity77

Established project with proven stability

 Bus Factor1

Top contributor holds 96.4% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~187 days

Recently: every ~374 days

Total

12

Last Release

326d ago

Major Versions

0.5.0 → 1.0.02020-12-29

1.0.0 → 2.0.02020-12-29

2.x-dev → 3.0.02025-06-26

### Community

Maintainers

![](https://www.gravatar.com/avatar/5c9f106db319e8698dcb4aedfe8034f0442d379ebbd78fcd67b884999b2236f1?d=identicon)[Sebobo](/maintainers/Sebobo)

---

Top Contributors

[![Sebobo](https://avatars.githubusercontent.com/u/596967?v=4)](https://github.com/Sebobo "Sebobo (54 commits)")[![klfman](https://avatars.githubusercontent.com/u/9661367?v=4)](https://github.com/klfman "klfman (1 commits)")[![mhsdesign](https://avatars.githubusercontent.com/u/85400359?v=4)](https://github.com/mhsdesign "mhsdesign (1 commits)")

---

Tags

critical-csshacktoberfestinline-stylesneos-cmscsscomponentsNeosstylesFUSIONNeos CMS

### Embed Badge

![Health badge](/badges/shel-critical-css/health.svg)

```
[![Health](https://phpackages.com/badges/shel-critical-css/health.svg)](https://phpackages.com/packages/shel-critical-css)
```

###  Alternatives

[almasaeed2010/adminlte

AdminLTE - admin control panel and dashboard that's based on Bootstrap 4

45.3k8.5M140](/packages/almasaeed2010-adminlte)[twig/cssinliner-extra

A Twig extension to allow inlining CSS

22918.5M55](/packages/twig-cssinliner-extra)[robsontenorio/mary

Gorgeous UI components for Livewire powered by daisyUI and Tailwind

1.5k454.7k15](/packages/robsontenorio-mary)[symfony/ux-twig-component

Twig components for Symfony

21914.8M162](/packages/symfony-ux-twig-component)[symfony/ux-live-component

Live components for Symfony

1635.6M72](/packages/symfony-ux-live-component)[area17/blast

Storybook for Laravel Blade

308664.1k](/packages/area17-blast)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
