shel / critical-css
允许在 Neos CMS 中内联和优化组件样式
Requires
- neos/neos: ~7.0 || ~8.0 || dev-master
README
本包提供了一些助手,允许向 Neos CMS 中的 Fusion 组件添加内联样式,并可以在本地或 HTML 文档的头部合并它们。默认情况下,样式被自动作用域,可以像任何其他 Fusion 对象一样动态定义。
根据定义的样式的哈希值动态生成 CSS 类。
这允许您将样式与组件放在同一个文件中,并能够覆盖它们。一个很好的用例是为您的关键 CSS 定义内联样式,当网站显示时应该立即加载,并延迟加载其他不需要立即加载的样式。
用例
- 定义“视窗顶部”内容应可用的关键 CSS。
- 为主题网站定义动态 CSS 变量。
- 包含具有可复用组件的 CSS。
- 为每个单独的页面提供一个最小的 CSS 集合。
支持
- 作用域样式
- 样式嵌套
- 具有特定选择器的全局样式
- 通过 http 组件自动将样式合并到文档头部
@media
和@supports
查询
此包不需要任何特定的浏览器功能。
目录
安装
在您的网站包中运行此操作
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。
自定义选择器
也可以使用自定义选择器来定位html
、body
或所有标签*
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的收集器在具有应用样式的缓存组件上存在问题。这可能导致文档中缺少样式。