我知道我可以使用[dir='ltr']
或[dir='rtl']
来选择具有特定值的dir属性的元素。
所以我可以定义例如
[dir='ltr'] .float-end {float:right}
[dir='rtl'] .float-end {float:left}
获得一个.float-end
类,当在一个分别带有ltr或rtl的元素中时,它会向左或向右浮动。
当我有一个文档的ltr子部分是rtl时,问题就开始了。
<div dir="rtl">
<div dir="ltr">
<div class="float-end"></div>
</div>
</div>
结果是两个规则匹配…在这个场景中,我只想匹配'ltr'的情况。
问题变得更糟,如果我想创建类,如start-20px
和end-20px
提供left:20px
和right:20px
,反之亦然,取决于上下文。
会导致left:20px
和right:20px
同时被应用....
我正在寻找如何克服这个问题的建议。
是否有一种方法依赖于任何给定类型元素的属性的最近值?
如果有帮助的话,这些都是在LESS mixins的上下文中完成的…
Thanks
问题在于CSS中当前可用的属性选择器没有文档语义。例如,您不能使用属性选择器来表示从其他元素继承的某些属性值。这是因为就属性选择器而言,如果元素的属性在文档树中没有在元素本身上指定某个值,那么它将不匹配选择器,即使该值是从其他地方派生的。
如前所述,您可以使用>
组合子将选择限制到最近的祖先,但这要求直接祖先具有指定的属性,当然,除非您自己确定,否则您无法保证这种情况。但是,如果您能够修改您的标记,那么这确实是最好的方法,即使这意味着您的标记中有一点冗余。我不认为LESS本身能够帮助你,因为它仍然取决于你的标记结构,这是它无法预测的。
值得注意的是,Selectors 4引入了一个:dir()
伪类,它根据文档语言的规则携带元素方向性的语义,这是属性选择器单独无法完成的。例如,以下示例中的div
和p
都将匹配:dir(ltr)
,但只有div
是[dir='ltr']
,因为p
没有指定dir
属性:
<div dir="ltr">
<p>Left-to-right text</p>
</div>
在您的情况下,您将能够分别使用.float-end:dir(ltr)
和.float-end:dir(rtl)
;你甚至不需要在祖先类上有伪类。
与[dir=]
属性选择器相比,:dir()
伪类类似于:lang()
和[lang|=]
,我在这里解释。
当然,作为一个新提案,:dir()
并没有在任何地方实现(除了Firefox的奇怪例外-我猜Mozilla想到了这个想法,实现了它,然后提议将其标准化)。与此同时,你将不得不绕过它的路线I des
现在在CSS规范中有一个建议的解决方案:逻辑属性。基本上,浏览器将不再基于其他元素的dir属性应用不同的属性值,而是开始拥有方向感知的属性值。
所以在一个完美的世界里,一旦这些完全支持,你可以写:
.float-end {
float: inline-end;
}
这些新值将存在于许多属性中,而不仅仅是float。截至2019年7月,除了微软(IE/Edge)之外,几乎所有人都支持。
嗯,我不能给你的第一个问题(关于浮动)的解决方案,但我可以给你一个关于第二个(左/右属性)的解决方案。
w3c
如果'left'和'right'都不是'auto',则位置为过度约束,其中一个必须被忽略。如果包含块的'direction'属性为'ltr',其值为'left'获胜,'right'变成了-'left'。如果"方向"的包含块为'rtl', 'right'优先,'left'被忽略。
好的。因此,在了解到我所期望的并不奏效(至少目前不是[2014年6月])之后,我最终采用了以下基于LESS的解决方案:
//提供一个mixin,根据当前的方向使用两个不同的规则集。
.ltr(@ltrRules) {
body[dir="ltr"] & , body[dir="rtl"] [dir="ltr"] &, body[dir="rtl"] [dir="ltr"]& { @ltrRules(); }
}
.rtl (@rtlRules) {
body[dir="rtl"] & , body[dir="ltr"] [dir="rtl"] &, body[dir="ltr"] [dir="rtl"]& { @rtlRules(); }
}
.bidi(@ltrRules,@rtlRules) {
.ltr(@ltrRules);
.rtl(@rtlRules);
}
// padding
// ------------------------------------------
.padding-start(@p) {
.bidi(
{ padding-left: @p } ,
{ padding-right: @p }
)
}
所以使用。padding-start(10;)来选择
.my .selector {
.padding-start(10px);
}
将最终生成以下CSS:
body[dir="ltr"] .my .selector,
body[dir="rtl"] [dir="ltr"] .my .selector,
body[dir="rtl"] [dir="ltr"].my .selector {
padding-left: 10px;
}
body[dir="rtl"] .my .selector,
body[dir="ltr"] [dir="trl"] .my .selector,
body[dir="ltr"] [dir="trl"].my .selector {
padding-right: 10px;
}
折衷方案是,我不能多次改变文档深度的方向,并且必须在body标签上初始看到方向。
也就是说,如果出于一些荒谬的原因,我将在未来的某一点上,当我将不得不更改目录两次以上,我可以使用相同的方法,并为body[dir="ltr"] [dir="rtl"] [dir="ltr"] &
等添加处理…
如果运气好的话,几年后有人会明白,添加start
和end
的语义是很重要的,它们分别在LTR上下文中被解释为left
和right
,反之亦然,在TRL上下文中使我所有的宏都冗余……[就像已经在text-align中做过的那样]。
我知道这是一个很晚的回复,但如果我的问题是正确的,它可以帮助别人。
这有意义吗?
[dir="ltr"] *:not([dir="rtl"]) .float-end,
[dir="ltr"] > .float-end{
float: right;
}
[dir="rtl"] *:not([dir="ltr"]) .float-end,
[dir="rtl"] > .float-end{
float: left;
}
这里的JSFiddle