shel/critical-css

允许在 Neos CMS 中内联和优化组件样式

安装次数: 1,715

依赖关系: 0

建议者: 0

安全性: 0

星星: 10

关注者: 4

分支: 3

开放问题: 1

类型:neos-plugin

2.0.3 2022-05-03 15:02 UTC

This package is auto-updated.

Last update: 2024-08-30 01:38:10 UTC


README

Latest Stable Version License Travis Build Status StyleCI

本包提供了一些助手,允许向 Neos CMS 中的 Fusion 组件添加内联样式,并可以在本地或 HTML 文档的头部合并它们。默认情况下,样式被自动作用域,可以像任何其他 Fusion 对象一样动态定义。

根据定义的样式的哈希值动态生成 CSS 类。

这允许您将样式与组件放在同一个文件中,并能够覆盖它们。一个很好的用例是为您的关键 CSS 定义内联样式,当网站显示时应该立即加载,并延迟加载其他不需要立即加载的样式。

用例

  • 定义“视窗顶部”内容应可用的关键 CSS。
  • 为主题网站定义动态 CSS 变量。
  • 包含具有可复用组件的 CSS。
  • 为每个单独的页面提供一个最小的 CSS 集合。

支持

  • 作用域样式
  • 样式嵌套
  • 具有特定选择器的全局样式
  • 通过 http 组件自动将样式合并到文档头部
  • @media@supports 查询

此包不需要任何特定的浏览器功能。

本包的灵感来源于 SvelteJSJSS

目录

安装

在您的网站包中运行此操作

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

然后,在您的项目根目录中运行 composer update

用法

添加内联样式

给定以下示例组件

prototype(My.Site:Component.Blockquote) < prototype(Neos.Fusion:Component) {
    text = ''
    
    renderer = afx`
        <blockquote>{props.text}</blockquote>
    `
    
    @process.styles = Shel.CriticalCSS:Styles {
        font-size = '2em'
        font-family = 'Comic Sans'
        padding = '.5rem'
    }
}

生成的 HTML 将类似于以下内容

<style data-inline>.style--cd7c679e3d{font-size:2m;font-family:Comic Sans;padding:.5rem;}</style>
<blockquote class="style--cd7c679e3d">My text</blockquote>

这将已经工作,但这样会有很多样式标签,可能会有重复。

此包自动将“样式收集器”应用到文档中,收集所有这些内联样式。因此,所有样式标签首先被收集,然后合并到一个列表中,删除重复项,并作为一个样式标签插入到 HTML 头部。

在应用样式时要注意,不仅应用到一个标签,而是一组标签。然后它将自动生成一个类似于 Fusion 中 Augmenter 的包装标签。

嵌套样式

再次提供一个类似的示例,但带有嵌套样式

prototype(My.Site:Component.Blockquote) < prototype(Neos.Fusion:Component) {
    text = ''
    link = ''
    
    renderer = afx`
        <blockquote>
            {props.text} 
            <a href={props.link}>Read more</a>
        </blockquote>
    `
    
    @process.styles = Shel.CriticalCSS:Styles {
        font-size = '2em'
        font-family = 'Comic Sans'
        padding = '.5rem'
        a {
            color = 'blue'
            text-decoration = 'underline'
        }
    }
}           

在嵌套时,您可以使用 Neos.Fusion:DataStructure 或像示例中那样的简单嵌套括号。

生成的 HTML 将类似于以下内容

<style data-inline>.style--cd7c679e3d{font-size:2m;font-family:Comic Sans;padding:.5rem;}.style--cd7c679e3d a{color:blue;text-decoration:underline;}</style>
<blockquote class="style--cd7c679e3d">My text</blockquote>

在单个组件中使用多个样式

要为组件的几个部分设置样式,您可以这样做

prototype(My.Site:Component.Complex) < prototype(Neos.Fusion:Component) {
    headline = ''
    text = ''
    footer = ''
    
    renderer = afx`
        <section>
            <header>
                <Shel.CriticalCSS:Styles @path="@process.styles"
                    font-weight="bold"
                    color="black"
                />
                {props.headline}
            </header>
            
            <div>{props.text}</div>
            
            <footer>
                <Shel.CriticalCSS:Styles @path="@process.styles"
                    font-size="80%"
                    color="gray"
                />
                {props.footer}
            </footer>
        </section>
    `
    
    @process.styles = Shel.CriticalCSS:Styles {
        padding = '.5rem'
        div {
            margin = '1rem 0'
        }
    }
}    

这将生成三个具有三个不同 CSS 类的样式标签。所有这些都将被收集器拾取。

使用 Fusion 助手的简写

在您的包中的某个地方定义简短的原型

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

(注意需要的冒号:CSS:Style。Fusion 不在乎,但 afx 会将 CssStyle 转换为 Neos.Fusion:Tag。Afx 需要一种方法来区分。)

然后你可以像这样编写前面的例子

prototype(My.Site:Component.Complex) < prototype(Neos.Fusion:Component) {
    headline = ''
    text = ''
    footer = ''
    
    renderer = afx`
        <section>
            <header>
                <CSS:Style @path="@process.styles"
                    font-weight="bold"
                    color="black"
                />
                {props.headline}
            </header>
            
            <div>{props.text}</div>
            
            <footer>
                <CSS:Style @path="@process.styles"
                    font-size="80%"
                    color="gray"
                />
                {props.footer}
            </footer>
        </section>
    `
    
    @process.styles = CSS:Style {
        padding = '.5rem'   
        div {
            margin = '1rem 0'
        }
    }
}   

使用 props 修改样式

这种方法允许你通过使用props轻松地修改样式

prototype(My.Site:Component.TextBanner) < prototype(Neos.Fusion:Component) {
    text = ''
    backgroundColor = '#4444ff'        
    
    renderer = afx`
        <div>
            <Shel.CriticalCSS:Styles @path="@process.styles"
                background-color={props.backgroundColor}
            />
            {props.text}
        </div>
    `
}   

请记住,你只能在renderer内部某处应用了styles对象时才能访问props。你可以通过renderer.@process.styles或像示例代码那样来实现。

使用 CSS 变量的用法

你也可以这样轻松地定义全局或局部CSS变量

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')}
                }
            }
        }
    }
}

然后当你有一个这样的嵌套组件时

prototype(My.Site:Component.Blockquote) < prototype(Neos.Fusion:Component) {
    text = ''
    
    renderer = afx`
        <blockquote>{props.text}</blockquote>
    `
    
    @process.styles = Shel.CriticalCSS:Styles {
        color = 'var(--theme-color)'
    }
}

当允许编辑器定义主题并将这些值放入CSS变量时,我推荐使用我的colorpicker(颜色选择器)插件,用于Neos CMS。

自定义选择器

也可以使用自定义选择器来定位htmlbody或所有标签*

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'
            }
        }
    }
}

从文件插入样式

此包包含一个Fusion助手,可以从文件中插入内联样式。虽然进行了作用域限制,但样式标签将被样式收集器获取。

prototype(My.Site:Component.Test) < prototype(Neos.Fusion:Component) {
    text = ''
    
    renderer = afx`
        <Shel.CriticalCSS:LoadStyles path="resource://My.Site/Private/Fusion/Components/Test/style.css"/>        
        <div>{props.text}</div>
    `
}

也作为process使用

prototype(My.Site:Component.Test) < prototype(Neos.Fusion:Component) {
    text = ''
    
    renderer = afx`    
        <div>{props.text}</div>
    `
    
    @process.addStyles = Shel.CriticalCSS:LoadStyles {
        path="resource://My.Site/Private/Fusion/Components/Test/style.css"
    }    
}

其他示例

您还可以查看功能测试固定值,以查看已验证的使用案例。

修改样式收集器行为

默认情况下,收集器作为http中间件在请求链的末尾应用。它将所有由本包生成的内联样式合并为一个样式标签放在html头部。在此过程中会移除重复项。您可以使用此设置禁用此行为

Shel:
    CriticalCSS:
        mergeStyles:
            enabled: false

Fusion 样式收集器

此包还包含一个通过Fusion的第二个收集方法。可以使用Shel.CriticalCSS:StyleCollector助手以与process类似的方式合并所有内联样式标签。在DOM内部这样做时,样式标签将在应用的地方添加。当应用于整个文档时,它也将样式合并到html头部。

在某些情况下,这种方法可能很有帮助,但当包含的组件有自己的缓存配置时,可能会出现问题。这就是为什么http组件更受青睐,因为它可以在文档级别解决这个问题。但是,如果由于某些原因不能使用默认设置,这可能会有所帮助。

限制

在 Neos UI 中插入新元素

在处理后端时,样式收集器不会自动收集新插入元素中的样式块。当添加的元素以某种方式像在滑块中一样用JavaScript处理时,这可能会引起一些问题。

缓存

如样式收集器部分所述,基于Fusion的收集器在具有应用样式的缓存组件上存在问题。这可能导致文档中缺少样式。