97
将@extend在萨斯指令是一个功能强大的指令,有利于规则和选择之间的关系的共享。但是,如果不仔细实施,可能会产生不良副作用。值得庆幸的是,有许多@extend有效使用的策略可以防止这些副作用,并产生干净,有组织的CSS。潮州网站制作
通过@extend详细检查和探索这些不同的策略,您可以准确地准确预测使用时会发生什么@extend,并在何时使用@mixin和何时使用时做出更明智的决策@extend,以确保最佳组织并限制样式表中未使用的样式。
将@extend在萨斯指令是一个功能强大的指令,有利于规则和选择之间的关系的共享。但是,如果不仔细实施,可能会产生不良副作用。
值得庆幸的是,有许多@extend有效使用的策略可以防止这些副作用,并产生干净,有组织的CSS。
通过@extend详细研究和探索这些不同的策略,您可以:
准确预测您使用时会发生什么@extend,
并在何时使用@mixin和何时使用时做出更明智的决定@extend,以确保最佳组织并限制样式表中未使用的样式。
@extend正如文档所示,Sass' 指令不仅仅是将扩展选择器组合在一起。@extend选择器时会发生两件大事:
确定目标“ 简单选择器 ” ;
使用以下内容在目标选择器上形成约束:
正在进行扩展的选择器,
和正在扩展的选择器。
让我们以一个例子来打破这个。请考虑以下代码:
.foo.bar { color: green; }.ancestor .descendant { @extend .bar; } // .bar is being extended
目标简单选择器标识为.descendant。
形成两个约束:
.bar(以及扩展它的任何内容)必须使类.foo成为绿色,
.descendant必须是...的后代.ancestor。
使用此信息,该@extend指令生成此规则集:
.foo.bar, .ancestor .foo.descendant { color: green; }
目标选择器.descendant现在满足约束要求:它有一个类.foo,它是一个祖先.ancestor。
@extend下面列出了一些常见方案。注意隐式放在目标选择器上的约束(要求)以及如何在输出的CSS中实现这些约束:
// Extending a selector with an ancestor.first { color: green; }.second { @extend .first; }.ancestor .first { background: white; }// CSS.first, .second { color: green; }.ancestor .first, .ancestor .second { background: white; }// Extending a selector with a descendant.first .descendant { color: green; }.second { @extend .first; }// CSS.first .descendant, .second .descendant { color: green; }// Extending a selector within a compound selector.one.two { color: green; }.three { @extend .one; }// CSS.one.two, .two.three { color: green; } // Extending a selector using a complex selector.foo.bar { color: green; }.complex .selector { @extend .bar; }// CSS.foo.bar, .complex .foo.selector { color: green; }// Alternating ancestors.ancestor-1 .foo { color: green; }.ancestor-2 .bar { @extend .foo; }// CSS// Notice how the ancestors switch places to // maintain the general ancestral constraints.ancestor-1 .foo, .ancestor-1 .ancestor-2 .bar, .ancestor-2 .ancestor-1 .bar { color: green;}// Combinator with common ancestor.foo.bar + .sibling { color: green; }.foo .descendant { @extend .sibling; }// CSS// Notice how .foo is repeated to preserve// constraint of .foo.bar.foo.bar + .sibling, .foo .foo.bar + .descendant { color: green;}
以上示例中有一些要点:
扩展服从选择器约束。。在最后一个例子中,.descendant是兄弟姐妹.foo.bar,而不是.foo。它也是一个后代.foo,既然.foo不能同时是祖先和兄弟,它会输出两次以维持这些各自的约束。
祖先和后代选择者容易发生排列爆炸。。祖先(以形式.ancestor .descendant)可以是父母,祖父母以外的任何东西。当具有祖先的选择器扩展具有祖先的其他选择器时,必须考虑所有这些排列。
扩展是一种单向操作。。当.bar延伸.foo,.bar密切地意识到之间的关系.foo的选择和,而不是周围的其他方法。是的,选择者可以相互对立@extend。
在@extend和@mixin指令是不完全一样的。虽然@mixin可以为多个选择器复制并通过参数自定义的输出规则,但@extend使用上述机制进行规则共享,以实现三个主要目的:
继承可以被扩展选择器覆盖的选择器之间的规则集;
特征或可共享的规则集;
关系选择器之间,当与一定义的关系的选择器经由组合子延伸被保持(例如,>,+,~,等等)。
既然我们知道如何使用@extend以及究竟是什么导致选择器爆炸,那么让我们看看我们可以实现的一些策略,以便在选择器之间正确地共享样式。
Sass包含一种特殊类型的选择器,称为占位符选择器,它的字面意思是与之一起使用@extend。这些是非常通用的选择器,因为它们:
当然可以扩展 ;
在CSS输出中被忽略,这可以防止不必要的输出;
可以像Sass中的任何其他选择器一样动态声明,这意味着你可以%do-#{$this}在非动态混合中使用它。
当你@extend %placeholders,爆炸性副作用减少,因为你有一个较少的共享选择器与最终的CSS输出结合。
通过扩展父(占位符)选择器来考虑以下继承示例:
// Don't do this:%button { // … parent button styles}.button { @extend %button; // … button styles}.button-primary { @extend %button; // … primary button styles}.button-secondary { @extend %button; // … secondary button styles}// CSS - we want to avoid this:.button, .button-primary, .button-secondary { // button styles}.button-primary { /* … */ }.button-secondary { /* … */ }
当多次扩展相同的选择器时,问问自己,所有这些扩展选择器有什么共同之处?然后,您可以通过使用公共选择器进行重构来限制选择器的扩展频率,例如,而不是,以便唯一的扩展名为。.button.primary.button-primary.button { @extend %button; }
使用特征可以很难实现先前的策略,根据定义,可以在许多不相关的选择器之间共享。一般来说,特征没有等级约束 ; 也就是说,它们(通常)与使用它的选择器和其他选择器之间的关系无关。因此,它们可以与@extend或一起使用@mixin。
我(个人)会选择@extend一个有很多规则的特质。该输出CSS 意志集团无关选择与该性状规则集,虽然这不是一个大问题-样式表维护您的发生.sass或.scss文件,而不是你的.css文件,并有几个性能之间的平衡,在一般。
另一方面,我会使用@mixin简洁且经常使用的规则集,例如clearfix。扩展它会导致CSS为这个小特征输出大量选择器。使用它作为mixin将使输出的CSS更具可读性,并且重复是可以的,因为规则集很小。
所以,这里有一些使用特征的一般指导原则:
扩展具有长规则集或不经常使用的特征。。这样可以保存输出的CSS DRY,并有助于在CSS中对规则集进行分组,从而提高浏览器调试的清晰度。
Mixin特征更通用,更短且经常使用。。你可以使用@extend这些类型的特征,但是你更容易受到选择器爆炸的风险。
将重复的规则集粘贴在%placeholder特征或特征中@mixin。这只是将SCSS尽可能保持干燥的一般做法。
这是最重要的用途之一@extend。样式表中选择器之间的关系可能变得非常复杂,并且@extend是完成工作的完美工具 - 您无法@mixin单独表达关系。选择器之间的关系与表示组合子,如>,+,~或白空间祖先组合子。CSS中可以存在许多不同类型的关系,即使不是那么明显的关系:
.parent > .child
.ancestor .descendant
.sibling ~ .sibling
.sibling + .adjacent-sibling
.sibling + * ~ .non-adjacent-sibling
.parent > * > .grandchild
.parent > * .non-child-descendant
.uncle ~ * > .nephew
* + *,任何相邻的兄弟关系,或lobotomized猫头鹰选择器
CSS使我们能够根据选择器与其他选择器的关系为选择器定义样式。这些使用组合器的关系定义选择器称为复选择器,它们比独立的简单或复合选择器部分具有更高的特异性。因此,定义为关系的样式比独立选择器中定义的样式具有更高的普遍性。
以下策略解决了如何扩展关系的深度。
还记得当你有两个祖先关系(例如.foo .bar {…} .baz .qux { @extend .bar; })时会发生什么?意识到多个扩展的祖先关系容易引起选择器爆炸,我们应该始终定义我们的关系,并保持它们是片面的。还有什么比%placeholder选择器更好地定义关系,以减少CSS输出?
假设您希望按钮在模态中的样式有点不同,并且您希望相邻按钮之间有一点空间。以下是使用占位符的关系:
%button { // … button styles + %button { margin-left: 1rem; }}%modal { // … modal styles %button { // … modal-specific button styles }}// "Exported" classes.button { @extend %button; }.modal { @extend %modal; }
请注意,定义了两个关系:兄弟%button + %button关系和祖先%modal %button关系。这些关系在占位符中只定义一次,输出的CSS正是我们所期望的:
.button { /* … button styles */ }.button + .button { margin-left: 1rem; }.modal { /* … modal styles */ }.modal .button { /* … modal-specific button styles */ }
这遵循第一个策略:尽可能多地扩展选择器。在编写标记和CSS选择器时,尽可能少的选择器代表实体将阻止选择器爆炸,即使这意味着您必须向标记添加语义类以消除选择器。
%button { // … button styles }// Avoid this:button, input[type="button"], input[type="submit"], .button { @extend %button;}// Try this instead, and add the class .button// for every type of button in the HTML.button { @extend %button;}
这两个组合子- .ancestor .descendant和.sibling ~ .general-sibling,分别为-是最容易选择的爆炸。为什么?他们的约束不如其他组合者严格。后代可以是孩子,孙子等。一般兄弟可以相邻,一个前面,两个前面等。
如果两个复杂的选择器都具有后代或一般兄弟组合器,则必须在输出的CSS中考虑所有可能性。这就是为什么你应该确保只有extendee或extender有一个后代或一般的兄弟组合,而不是两者。遵循上面关于仅从中扩展的指导%placeholders是强制执行此操作的好方法。
%modal { // … modal styles // Relationship: a %button that is a descendant of %modal %button { /* … modal-button styles */ }}// Don't do this!.modal { @extend %modal; // This is unnecessary - the relationship // is already defined! .button { @extend %button; }}// Do this - keep it simple!.modal { @extend %modal; }.button { @extend %button; }
通过单独%placeholders表示修改后的组件,您可以扩展而不会产生混淆复合和/或复杂选择器的风险。例如,@extend %button%active;风险很大,但@extend %button-active;不是。
%button { // … button styles &-active { // same as %button-active // … active button styles } &-disabled { // … disabled button styles }}.button { @extend %button; &.active { @extend %button-active; } &:disabled { @extend %button-disabled; }}
你可能在想,“我认为@extend在媒体查询中使用目前是不可能的。”这部分是正确的,但也有些误导。事实是,您只能在同一媒体查询中扩展选择器,并且,出于所有意图和目的,这就足够了。
然而,重要的是你的选择器是有意义的,因为你可以用适当的意图声明它们。如果您尝试在媒体查询中扩展外部选择器,那么这是一个明显的利益冲突 - 一个选择器的意图通常应用,而另一个选择器的意图仅应用于当前媒体上下文。
例如,由于媒体查询限制,下面的SCSS不起作用,更重要的是,因为意图不明确:
%panel { display: block; float: left; width: 100%; // … other panel styles}%panel-half { width: 50%; }.panel { @extend %panel; &.half { @extend %panel-half; }}// This will NOT work and will throw this error:// You may not @extend an outer selector from within @media.// You may only @extend selectors within the same directive.@media (max-width: 700px) { .panel-mobile { @extend %panel; &.half { @extend %panel-half; } }}
那么,这里出了什么问题?在定义时%panel,意图是“这个面板应该具有这种样式”,而我们试图导出.panel-mobile为“此面板应仅在此媒体查询上下文中具有此样式。”这是一个明显的错误传达。
解决方案是将extendee意图与扩展器意图相匹配,尤其是在@media查询方面。换句话说,如果您希望扩展程序仅为特定媒体查询携带某些样式,则它应仅在同一@media查询中扩展,或者,也可以使用中断@media查询@at-root。
让我们看看如何使用以上两个建议修改我们的代码:
// Solution 1: Extend within the same media query%panel { /* … */ }%panel-half { /* … */ }// Define extendees with the same intent as extenders@media (max-width: 700px) { %panel-mobile { /* … */ } %panel-mobile-half { /* … */ }}.panel { @extend %panel; &.half { @extend %panel-half; }
以下策略解决了如何扩展关系的深度。
还记得当你有两个祖先关系(例如.foo .bar {…} .baz .qux { @extend .bar; })时会发生什么?意识到多个扩展的祖先关系容易引起选择器爆炸,我们应该始终定义我们的关系,并保持它们是片面的。还有什么比%placeholder选择器更好地定义关系,以减少CSS输出?
假设您希望按钮在模态中的样式有点不同,并且您希望相邻按钮之间有一点空间。以下是使用占位符的关系:
%button { // … button styles + %button { margin-left: 1rem; }}%modal { // … modal styles %button { // … modal-specific button styles }}// "Exported" classes.button { @extend %button; }.modal { @extend %modal; }
请注意,定义了两个关系:兄弟%button + %button关系和祖先%modal %button关系。这些关系在占位符中只定义一次,输出的CSS正是我们所期望的:
.button { /* … button styles */ }.button + .button { margin-left: 1rem; }.modal { /* … modal styles */ }.modal .button { /* … modal-specific button styles */ }
这遵循第一个策略:尽可能多地扩展选择器。在编写标记和CSS选择器时,尽可能少的选择器代表实体将阻止选择器爆炸,即使这意味着您必须向标记添加语义类以消除选择器。
%button { // … button styles }// Avoid this:button, input[type="button"], input[type="submit"], .button { @extend %button;}// Try this instead, and add the class .button// for every type of button in the HTML.button { @extend %button;}
这两个组合子- .ancestor .descendant和.sibling ~ .general-sibling,分别为-是最容易选择的爆炸。为什么?他们的约束不如其他组合者严格。后代可以是孩子,孙子等。一般兄弟可以相邻,一个前面,两个前面等。
如果两个复杂的选择器都具有后代或一般兄弟组合器,则必须在输出的CSS中考虑所有可能性。这就是为什么你应该确保只有extendee或extender有一个后代或一般的兄弟组合,而不是两者。遵循上面关于仅从中扩展的指导%placeholders是强制执行此操作的好方法。
%modal { // … modal styles // Relationship: a %button that is a descendant of %modal %button { /* … modal-button styles */ }}// Don't do this!.modal { @extend %modal; // This is unnecessary - the relationship // is already defined! .button { @extend %button; }}// Do this - keep it simple!.modal { @extend %modal; }.button { @extend %button; }
通过单独%placeholders表示修改后的组件,您可以扩展而不会产生混淆复合和/或复杂选择器的风险。例如,@extend %button%active;风险很大,但@extend %button-active;不是。
%button { // … button styles &-active { // same as %button-active // … active button styles } &-disabled { // … disabled button styles }}.button { @extend %button; &.active { @extend %button-active; } &:disabled { @extend %button-disabled; }}
你可能在想,“我认为@extend在媒体查询中使用目前是不可能的。”这部分是正确的,但也有些误导。事实是,您只能在同一媒体查询中扩展选择器,并且,出于所有意图和目的,这就足够了。
然而,重要的是你的选择器是有意义的,因为你可以用适当的意图声明它们。如果您尝试在媒体查询中扩展外部选择器,那么这是一个明显的利益冲突 - 一个选择器的意图通常应用,而另一个选择器的意图仅应用于当前媒体上下文。
例如,由于媒体查询限制,下面的SCSS不起作用,更重要的是,因为意图不明确:
%panel { display: block; float: left; width: 100%; // … other panel styles}%panel-half { width: 50%; }.panel { @extend %panel; &.half { @extend %panel-half; }}// This will NOT work and will throw this error:// You may not @extend an outer selector from within @media.// You may only @extend selectors within the same directive.@media (max-width: 700px) { .panel-mobile { @extend %panel; &.half { @extend %panel-half; } }}
那么,这里出了什么问题?在定义时%panel,意图是“这个面板应该具有这种样式”,而我们试图导出.panel-mobile为“此面板应仅在此媒体查询上下文中具有此样式。”这是一个明显的错误传达。
解决方案是将extendee意图与扩展器意图相匹配,尤其是在@media查询方面。换句话说,如果您希望扩展程序仅为特定媒体查询携带某些样式,则它应仅在同一@media查询中扩展,或者,也可以使用中断@media查询@at-root。
让我们看看如何使用以上两个建议修改我们的代码:
// Solution 1: Extend within the same media query%panel { /* … */ }%panel-half { /* … */ }// Define extendees with the same intent as extenders@media (max-width: 700px) { %panel-mobile { /* … */ } %panel-mobile-half { /* … */ }}.panel { @extend %panel; &.half { @extend %panel-half; } // This WILL work! @media (max-width: 700px) { &-mobile { @extend %panel-mobile; &.half { @extend %panel-mobile-half; } } }}
// Solution 2: Break out of '@media' with '@at-root'%panel { display: block; float: left; // … other panel styles}// Separation of intent%panel-full { width: 100%; }%panel-half { width: 50%; }@media (max-width: 700px) { %panel-mobile-full { width: 100%; } %panel-mobile-half { width: 50%; }}.panel { @extend %panel; &.half { @extend %panel-half; } @media (max-width: 700px) { &-mobile, &-mobile-half { // General panel styling intent is maintained @at-root (without: media) { @extend %panel; } } &-mobile { @extend %panel-mobile-full; &.half { @extend %panel-mobile-half; } } }}
有时候,很难遵守指南,你应该@extend尽可能少地选择一个选择器。以HTML标题为例:h1, h2, h3, h4, h5, h6。其中有六个,并且无法使用一个简单的选择器选择它们。一种解决方案是给他们所有的一类.heading,但如果你正在为未来建设,那就有更好的方法。
输入CSS 4的:matches()伪选择器。这个选择器允许你在一定程度上模仿@extend原生CSS中的功能,而不会出现选择器爆炸(我们已经学会了如何避免)。最好的部分是,Sass :matches()与相关的假选择器很好地配合。让我们的标题样式来证明:
// With :matches():matches(%heading) { // … heading styles}// Relationship: any heading that is a descendant of %section-foo%section-foo :matches(%heading) { /* … */ }h1, h2, h3, h4, h5, h6 { @extend %heading;}.section-foo { @extend %section-foo; }// CSS output - much better than this selector explosion:// .section-foo h1, .section-foo h2, .section-foo h3, .section-foo h4, .section-foo h5, .section-foo h6.section-foo :matches(h1, h2, h3, h4, h5, h6) { // … section-foo heading style}
今天,你必须分别使用:-webkit-any()和:moz-any()替代:matches()WebKit浏览器和Firefox,直到它们原生支持:matches()。使用Internet Explorer,你运气不好(这并不奇怪)。在所有现代浏览器中实现CSS 4之前,这是一个很好的指导方针。
该@extend指令无所畏惧,而且功能多样。了解如何@extend工作并牢记上述指导原则将使您能够@extend充分发挥其优势 - 无论您使用哪种导出选择器(类,属性等),都可以减少CSS输出并保持关系完好无损。明智地使用@mixin和@extend指令 - 它们意味着在你组织良好的样式表中共存。
潮州网站制作
最新文章
随机推荐