CSS 预处理器,可以在 @media 查询中定义变量
Posted
技术标签:
【中文标题】CSS 预处理器,可以在 @media 查询中定义变量【英文标题】:CSS pre-processor with a possibility to define variables in a @media query 【发布时间】:2012-12-17 19:47:30 【问题描述】:目前,我使用 LESS 作为我的主要 CSS 预处理器。我有(而且我相信很多人都有这种需要)在@media
查询中定义变量,例如:
@media screen and (max-width: 479px)
myVar: 10px;
@media screen and (min-width: 480px) and (max-width: 767px)
myVar: 20px;
@media screen and (min-width: 768px)
myVar: 30px;
.myElement
padding: @myVar;
由于编译性质,这在 LESS 中不起作用(@myVar
仅在每个特定 @media
的范围内定义,而不是全局定义)。即使我在媒体查询之前全局定义了@myVar
,它也不会根据媒体查询进行更新,并且.myElement
无论如何都会获得该初始值。
所以,问题是,是否有可能在任何其他 CSS 预处理器中实现这一点,或者我们注定要在每个媒体查询中覆盖 .myElement
?在这个最简单的示例中不是问题,但在实际项目中,这可以节省大量时间和复制/粘贴。
编辑: 不是解决方案,而是我的特定项目的解决方法:
-
将
<html>
上的字体大小设置为基本字体大小
myVar
LESS 变量在 rem
而不是 px
中定义为基本字体大小的派生词
使用@media
查询来调整不同媒体的基本字体大小。
可选 将REM unit polyfill 用于尚不支持rem
(http://caniuse.com/#search=rem) 的浏览器。这在 IE 8 及更低版本中不起作用,但不是因为缺乏对 rem
- it doesn't support media queries 的支持。因此,无论如何,IE8 及以下版本都会获得全尺寸无媒体查询样式表。
代码sn-p:
@myVar: .77rem; // roughly 10px, 20px and 30px respectively
html font-size: 13px
@media screen and (min-width: 480px) and (max-width: 767px)
html font-size: 26px
@media screen and (min-width: 768px)
html font-size: 39px
.myElement
padding: @myVar;
这里是一个JSBin,其中包含更广泛的示例,它将不同字体大小的元素与不同的测量块混合在一起。
简单灵活,满足我的需求。希望对其他人有所帮助。
【问题讨论】:
我认为这在任何 CSS 编译器中都是不可能的。编译器必须为您生成@media ... .myElement padding: ...
。尽管这很有可能,但这将无法控制您。为什么不直接在 @media ... ...
查询中包含 .myElement ...
或使用在其中导入的 mixins(以减少重复)?
@try-catch-finally,重复的问题在于维护。如果我有相当多的媒体查询甚至更多元素,取决于媒体查询相关变量,这将是一场维护噩梦。
如果这是您对媒体查询所做的事情的一个示例,那么您就是导致维护噩梦的人。根据浏览器的宽度,您的填充有不同的 px 值?请改用百分比。
@cimmanon,我很欣赏你的意见,但你认为我并没有真正使用 'myVar' 和 '。 myElement' 在真实的代码中,你呢?我认为这不是很聪明。如果我举一个真实的例子,这个问题将是不可读的。感谢您的宝贵时间。
@spliter 变量和类的名称无关紧要。我只能根据您提供的内容来判断,我的观点仍然成立:您是造成维护噩梦的人。如果你把事情简单化太多,你最终会得到过于简单的解决方案。
【参考方案1】:
让我更直接地回答这个问题:
“是否有可能在任何其他 CSS 预处理器中实现这一点,或者我们 注定要覆盖每个媒体查询中的
.myElement
?”
答案实际上存在于问题中。因为 LESS(和其他类似工具)是一个“预处理器”,所以@media
在编译时对它没有任何意义,因为它不会查看浏览器的媒体状态来进行预处理。 @media
状态仅在预处理之后 相关,此时任何@someVariable
都已被计算。这就是为什么您尝试做的事情行不通的原因。您的 @myVar
只能作为 CSS 样式表中的单个值输出,并且该输出发生在 @media
评估浏览器状态之前。
因此,它与媒体查询的“全局”或“本地”范围无关,而是 LESS 使用变量将代码编译为 CSS 的事实,而支付费用的是 CSS(而不是 LESS)关注@media
查询信息。
有关使用 LESS 构建媒体查询的进一步讨论,以使它们都在一起而不是分散在整个代码中,请参阅this question。
【讨论】:
感谢@ScottS 的详细解释。我确实使用了问题中提到的解决方法,但无论如何您的回答都准确地回答了这个问题。因此我接受它。 “@media
在编译时对它没有任何意义”:这不太正确,LESS 执行 bubbling for @media
queries。
@Flimm:关于“冒泡”是正确的,但我所说的“没有任何意义”的上下文并不是指 LESS 如何预处理 @media
在最终 css 中的位置,而是指以下内容关于“浏览器的媒体状态”的因果子句对 LESS 预处理毫无意义。 LESS 在编译时没有读取浏览器的媒体状态,因此 @media
本身没有不同的值,因此不能用于分配要在 LESS 编译期间使用的变量(如问题所示)。
好的,但是LESS编译器不需要读取浏览器的状态,它是could be done like this。
@Flimm:有很多方法可以设置变量(我相信有些人会发现你的链接很有用)。但问题具体是关于设置一个使用 outside 的变量 @media
块只需通过 @media
引用进行该变量的设置,这样就不必“覆盖 .myElement
在每个媒体查询中”(根据 OP)。也就是说,他不希望在他的最终 css 中有一堆 @media
对 .myElement
的重新定义。我的答案是解释 为什么 LESS 配置无法生成他想要的 css。【参考方案2】:
您可以将其重构为将媒体查询放入变量中,然后在元素中使用它们。
例子:
@phone: ~"screen and (max-width: 479px)";
@tablet: ~"screen and (min-width: 480px) and (max-width: 767px)";
@desktop: ~"screen and (min-width: 768px)";
.myElement
@media @phone padding: 10px;
@media @tablet padding: 20px;
@media @desktop padding: 30px;
产生:
@media screen and (max-width: 479px)
.myElement
padding: 10px;
@media screen and (min-width: 480px) and (max-width: 767px)
.myElement
padding: 20px;
@media screen and (min-width: 768px)
.myElement
padding: 30px;
整个使媒体查询成为嵌入变量中的未解析文字并不完全漂亮,但也有助于标准化媒体查询。
而且它有助于提高可读性,因为.myElement
的所有三个行为都包含在一个定义中,并且没有在其他地方更改(可能是完全不同的文件),这使得“调试”变得困难。
【讨论】:
OP 听起来他想为大量元素使用这种模式。这将引入 很多 的 CSS 膨胀:每次在某物上设置填充时 3 次媒体查询。 谢谢西蒙娜。看起来很有趣。但不完全是我需要的。我真的需要根据媒体查询设置变量,而不是正在调整的类。我有很多不同的类取决于同一个变量,正如@cimmanon 指出的那样,它会非常容易导致 CSS 膨胀。【参考方案3】:怎么样:
@media screen and (max-width: 479px)
.myElement(10px);
@media screen and (min-width: 768px)
.myElement(30px);
.myElement(@myVar)
.myElement
padding: @myVar;
【讨论】:
谢谢巴拉兹。这确实有助于减少维护麻烦。但是,这仍然意味着根据变量将每个元素复制/粘贴到每个媒体查询中 ... 你也可以像 .variableRules(@var1, @var2...) ... 这样只做一个 mixin,然后你只需要插入 1 行不同的参数。以上是关于CSS 预处理器,可以在 @media 查询中定义变量的主要内容,如果未能解决你的问题,请参考以下文章