Css last/deepest 匹配元素或属性以应用覆盖之前所有内容的规则
Css last/deepest match element or attribute to apply a rule that overrides everything prior
例如,
给定
<html dir=rtl>
<body>
<div>I am right to left</div>
<div>I am right to left
<div dir=ltr>I should be left to right
<div dir=rtl>I should be right to left</div>
</div>
</div>
</body>
</html>
我问这个问题是因为生成了嵌套内容,而且无法知道这会有多深。
理想情况下,CSS 规则应该能够应用基于最深匹配的特定规则。
规则:
[dir=rtl] {
text-align:right;
}
只会匹配第一个。理想情况下,您需要
[dir=rtl]:deepest {
text-align:right;
}
更新:
我意识到问题的框架可能仍然有点混乱,对此感到抱歉!
这是说明问题的代码:
.container {
padding:20px;
}
[dir=ltr] .container {
border:5px solid blue;
}
[dir=rtl] .container {
border:5px solid red;
}
<div id="searchHere">
<div dir=ltr>
<div class="container">
l t r
</div>
<div dir=rtl>
<div class="container">
r t l
</div>
<div>
<div class="container">
r t l
</div>
<div dir=ltr>
<div class="container">
l t r ( should be but is r t l colors instead )
</div>
</div>
</div>
</div>
</div>
</div>
为了阐明目标是什么,也就是说在更深层次上找到的任何匹配都应该应用于所有子匹配。
这可以通过使用例如唯一标识符来实现,因为这将覆盖先前的规则,或者通过使用定义更明确的 css 选择器。定义更明确的选择器可能是 div > div > div > div
... 但是,给定一个动态生成的内容,很难知道要定义的规则。
更新:
使所需元素可直接定位
在您的初始示例中,所需元素是可直接定位的,因此我的原始答案如下。
但是在您的评论中,您提到了您用 the Code Pen you shared 澄清的更复杂的事情。
您实际上想要完成的是针对某些元素的后代,这些元素也不是竞争元素的后代,在这种情况下,[dir=rtl] .container
与 [dir=ltr] .container
.
当前没有 CSS 选择器可以在没有干扰的情况下执行此操作(正如您在笔中所演示的那样),因此设置这些元素样式的最佳方法是确保它们可以直接定位根据其与具有 dir
属性集的最近父级的关系,将标识符 class 应用到每个。
如果您可以控制生成的标记,则应在模板生成之前处理模板中的逻辑,以便标记准备就绪。
但是如果您无法控制生成的标记,您可以将 classes 与 jQuery 结合使用 .filter
和传入的函数。
无论哪种方式,您都希望您的标记像这样结束:
<div id="searchHere">
<div dir=ltr>
<div class="container ltr">
l t r
</div>
<div dir=rtl>
<div class="container rtl">
r t l
</div>
<div>
<div class="container rtl">
r t l
</div>
<div dir=ltr>
<div class="container ltr">
l t r
</div>
</div>
</div>
</div>
</div>
</div>
一种jQuery方法
$(function () {
$('.container')
.filter(function () {
// Return elements whose closest parent w/ attribute 'dir' is 'rtl'
return $(this).closest('[dir]').attr('dir') === 'rtl';
})
.addClass('rtl') // Apply identifier class
.end()
.filter(function () {
// Return elements whose closest parent w/ attribute 'dir' is 'ltr'
return $(this).closest('[dir]').attr('dir') === 'ltr';
})
.addClass('ltr'); // Apply identifier class
});
.container {
padding: 20px;
}
.container.ltr {
border: 5px solid blue;
}
.container.rtl {
border: 5px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="searchHere">
<div dir=ltr>
<div class="container">
l t r
</div>
<div dir=rtl>
<div class="container">
r t l
</div>
<div>
<div class="container">
r t l
</div>
<div dir=ltr>
<div class="container">
l t r
</div>
</div>
</div>
</div>
</div>
</div>
原回答:
CSS 已经默认提供
CSS 本机行为是将样式应用于与给定选择器匹配的每个元素。
在您的示例中,规则 [dir=rtl] { text-align:right; }
将应用于 每个 匹配选择器 [dir=rtl]
的元素,而不仅仅是第一个。
此外,您的示例甚至不需要 CSS 即可工作,因为您使用的是 HTML dir
属性,因此浏览器将自动应用右对齐这些元素中的文本。
<body dir="rtl">
<div>I am right to left</div>
<div>I am right to left
<div dir="ltr">I should be left to right
<div dir="rtl">I should be right to left</div>
</div>
</div>
</body>
但即使在纯 CSS 示例中,您也只需要使用标准选择器来定位嵌套元素:
.rtl {
direction: rtl;
}
.ltr {
direction: ltr;
}
<body class="rtl">
<div>I am right to left</div>
<div>I am right to left
<div class="ltr">I should be left to right
<div dir="rtl">I should be right to left</div>
</div>
</div>
</body>
没有。
如果您可以生成 HTML 到未指定的深度,那么您可以为 CSS 生成它,但是我们没有 "innermost match" 选择器。
你能做的最好的事情是使用一个脚本生成 CSS,该脚本理解级别越深,oiot 级别越不重要。这与 HTML 和 CSS 的假设相反。
这似乎是可行的,使用 :dir 或 :lang 属性。
在 2015 年最好使用 :lang,因为大多数浏览器都支持它。
示例:
.container {
padding:20px;
}
:lang(ar) {
direction:rtl;
}
:lang(en) {
direction:ltr;
}
.container:lang(en) {
background-color:blue;
}
.container:lang(ar) {
background-color:red;
}
.container .a:lang(en) {
background-color:orange;
}
.container .a:lang(ar) {
background-color:yellow;
}
<div id="searchHere">
<div lang=en>
<div class="container">
l t r
<div class=a>
a
</div>
</div>
<div lang=ar>
<div class="container">
r t l
<div class=a>
a
</div>
</div>
<div>
<div class="container">
r t l
<div class=a>
a
</div>
</div>
<div lang=ar>
<div class="container">
r t l
<div class=a>
a
</div>
</div>
</div>
<div lang=en>
<div class="container">
l t r
<div class=a>
a
</div>
<div lang=ar>
<div class="container">
r t l
<div class=a>
a
<div lang=en>
<div class="container">
l t r
<div class=a>
a
</div>
<div>
<div>
<div lang=en>
<div class="container">
l t r
<div class=a>
a
</div>
</div>
</div>
<div lang=ar>
<div class="container">
r t l
<div class=a>
a
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
虽然这个例子用 ltr 和 rtl 证明了这一点,理论上可以使 :lang 表现为最深的匹配,例如使用 :lang(deepest-overrides-all) 虽然这可能不是 lang= deepest-overrides-all 应该在元素上定义。
例如,
给定
<html dir=rtl>
<body>
<div>I am right to left</div>
<div>I am right to left
<div dir=ltr>I should be left to right
<div dir=rtl>I should be right to left</div>
</div>
</div>
</body>
</html>
我问这个问题是因为生成了嵌套内容,而且无法知道这会有多深。
理想情况下,CSS 规则应该能够应用基于最深匹配的特定规则。
规则:
[dir=rtl] {
text-align:right;
}
只会匹配第一个。理想情况下,您需要
[dir=rtl]:deepest {
text-align:right;
}
更新:
我意识到问题的框架可能仍然有点混乱,对此感到抱歉!
这是说明问题的代码:
.container {
padding:20px;
}
[dir=ltr] .container {
border:5px solid blue;
}
[dir=rtl] .container {
border:5px solid red;
}
<div id="searchHere">
<div dir=ltr>
<div class="container">
l t r
</div>
<div dir=rtl>
<div class="container">
r t l
</div>
<div>
<div class="container">
r t l
</div>
<div dir=ltr>
<div class="container">
l t r ( should be but is r t l colors instead )
</div>
</div>
</div>
</div>
</div>
</div>
为了阐明目标是什么,也就是说在更深层次上找到的任何匹配都应该应用于所有子匹配。
这可以通过使用例如唯一标识符来实现,因为这将覆盖先前的规则,或者通过使用定义更明确的 css 选择器。定义更明确的选择器可能是 div > div > div > div
... 但是,给定一个动态生成的内容,很难知道要定义的规则。
更新:
使所需元素可直接定位
在您的初始示例中,所需元素是可直接定位的,因此我的原始答案如下。
但是在您的评论中,您提到了您用 the Code Pen you shared 澄清的更复杂的事情。
您实际上想要完成的是针对某些元素的后代,这些元素也不是竞争元素的后代,在这种情况下,[dir=rtl] .container
与 [dir=ltr] .container
.
当前没有 CSS 选择器可以在没有干扰的情况下执行此操作(正如您在笔中所演示的那样),因此设置这些元素样式的最佳方法是确保它们可以直接定位根据其与具有 dir
属性集的最近父级的关系,将标识符 class 应用到每个。
如果您可以控制生成的标记,则应在模板生成之前处理模板中的逻辑,以便标记准备就绪。
但是如果您无法控制生成的标记,您可以将 classes 与 jQuery 结合使用 .filter
和传入的函数。
无论哪种方式,您都希望您的标记像这样结束:
<div id="searchHere">
<div dir=ltr>
<div class="container ltr">
l t r
</div>
<div dir=rtl>
<div class="container rtl">
r t l
</div>
<div>
<div class="container rtl">
r t l
</div>
<div dir=ltr>
<div class="container ltr">
l t r
</div>
</div>
</div>
</div>
</div>
</div>
一种jQuery方法
$(function () {
$('.container')
.filter(function () {
// Return elements whose closest parent w/ attribute 'dir' is 'rtl'
return $(this).closest('[dir]').attr('dir') === 'rtl';
})
.addClass('rtl') // Apply identifier class
.end()
.filter(function () {
// Return elements whose closest parent w/ attribute 'dir' is 'ltr'
return $(this).closest('[dir]').attr('dir') === 'ltr';
})
.addClass('ltr'); // Apply identifier class
});
.container {
padding: 20px;
}
.container.ltr {
border: 5px solid blue;
}
.container.rtl {
border: 5px solid red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="searchHere">
<div dir=ltr>
<div class="container">
l t r
</div>
<div dir=rtl>
<div class="container">
r t l
</div>
<div>
<div class="container">
r t l
</div>
<div dir=ltr>
<div class="container">
l t r
</div>
</div>
</div>
</div>
</div>
</div>
原回答:
CSS 已经默认提供
CSS 本机行为是将样式应用于与给定选择器匹配的每个元素。
在您的示例中,规则 [dir=rtl] { text-align:right; }
将应用于 每个 匹配选择器 [dir=rtl]
的元素,而不仅仅是第一个。
此外,您的示例甚至不需要 CSS 即可工作,因为您使用的是 HTML dir
属性,因此浏览器将自动应用右对齐这些元素中的文本。
<body dir="rtl">
<div>I am right to left</div>
<div>I am right to left
<div dir="ltr">I should be left to right
<div dir="rtl">I should be right to left</div>
</div>
</div>
</body>
但即使在纯 CSS 示例中,您也只需要使用标准选择器来定位嵌套元素:
.rtl {
direction: rtl;
}
.ltr {
direction: ltr;
}
<body class="rtl">
<div>I am right to left</div>
<div>I am right to left
<div class="ltr">I should be left to right
<div dir="rtl">I should be right to left</div>
</div>
</div>
</body>
没有。
如果您可以生成 HTML 到未指定的深度,那么您可以为 CSS 生成它,但是我们没有 "innermost match" 选择器。
你能做的最好的事情是使用一个脚本生成 CSS,该脚本理解级别越深,oiot 级别越不重要。这与 HTML 和 CSS 的假设相反。
这似乎是可行的,使用 :dir 或 :lang 属性。
在 2015 年最好使用 :lang,因为大多数浏览器都支持它。
示例:
.container {
padding:20px;
}
:lang(ar) {
direction:rtl;
}
:lang(en) {
direction:ltr;
}
.container:lang(en) {
background-color:blue;
}
.container:lang(ar) {
background-color:red;
}
.container .a:lang(en) {
background-color:orange;
}
.container .a:lang(ar) {
background-color:yellow;
}
<div id="searchHere">
<div lang=en>
<div class="container">
l t r
<div class=a>
a
</div>
</div>
<div lang=ar>
<div class="container">
r t l
<div class=a>
a
</div>
</div>
<div>
<div class="container">
r t l
<div class=a>
a
</div>
</div>
<div lang=ar>
<div class="container">
r t l
<div class=a>
a
</div>
</div>
</div>
<div lang=en>
<div class="container">
l t r
<div class=a>
a
</div>
<div lang=ar>
<div class="container">
r t l
<div class=a>
a
<div lang=en>
<div class="container">
l t r
<div class=a>
a
</div>
<div>
<div>
<div lang=en>
<div class="container">
l t r
<div class=a>
a
</div>
</div>
</div>
<div lang=ar>
<div class="container">
r t l
<div class=a>
a
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
虽然这个例子用 ltr 和 rtl 证明了这一点,理论上可以使 :lang 表现为最深的匹配,例如使用 :lang(deepest-overrides-all) 虽然这可能不是 lang= deepest-overrides-all 应该在元素上定义。