【问题标题】:how to base a css rule on inherited value of dir attribute如何基于 dir 属性的继承值创建 CSS 规则
【发布时间】:2014-08-06 10:46:52
【问题描述】:

我知道我可以使用 [dir='ltr'][dir='rtl'] 来选择具有特定值的 dir 属性的元素。

所以我可以定义例如

 [dir='ltr'] .float-end {float:right}
 [dir='rtl'] .float-end {float:left}

获得一个.float-end 类,该类分别在具有 ltr 或 rtl 的元素内时向右或向左浮动。

当我有一个 rtl 文档的 ltr 子部分时,问题就开始了。

<div dir="rtl">
   <div dir="ltr">
      <div class="float-end"></div>
   </div>
</div>

发生的情况是两个规则都匹配...在这种情况下我只想匹配“ltr”大小写。

如果我想创建诸如start-20pxend-20px 之类的类来提供left:20pxright:20px,则问题会变得更糟,反之亦然,具体取决于上下文。

将导致同时应用left:20pxright:20px....

我正在寻找有关如何克服这个问题的建议。

有没有办法依赖于任何给定类型元素的属性的最接近值?

这一切都是在 LESS mixins 的上下文中完成的,如果它有助于某种方式的话......

谢谢

【问题讨论】:

  • [dir='ltr'] &gt; .float-end
  • hmmm.... 这与继承值有关吗?还是仅适用于具有指定属性的直接子代?我将不得不对此进行测试。
  • 所以它不够好:(我需要类似 [dir inherits 'ltr'] > .float-end ....
  • 也许我的理解不够好,但[dir='ltr'] &gt; .float-end:first-child {float:right} 是否符合要求?带有完整示例的提琴手将非常有助于完全理解您想要的内容。

标签: css css-selectors


【解决方案1】:

问题在于当前 CSS 中可用的属性选择器没有文档语义。例如,您不能使用属性选择器来表示从其他元素继承的某些属性值。这是因为就属性选择器而言,如果一个元素的属性没有在文档树中的元素本身上指定某个值,那么即使该值是从其他地方派生的,它也不会匹配该选择器。

如前所述,您可以使用 &gt; 组合器将选择限制为最近的祖先,但这需要直接祖先具有指定的属性,当然您无法保证是这种情况,除非您做出你自己确定。但是如果你能够修改你的标记,那么这确实是最好的方法,即使这意味着你的标记有一点冗余。我认为即使 LESS 本身也无法帮助您,因为它仍然取决于您的标记结构,这是它无法预料的。


值得一提的是,Selectors 4 引入了一个 :dir() pseudo-class,它基于文档语言的规则承载元素方向性的语义,这是单独的属性选择器无法完成的。例如,以下示例中的divp 都将匹配: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|=],我解释了here

当然,作为一个新提案,:dir() 并没有在任何地方实施(Firefox 是个奇怪的例外——我猜 Mozilla 想到了这个想法,实施了它,然后提议将其标准化) .与此同时,你必须通过我设计的路线来解决它

【讨论】:

  • 我在想,尽管 HTML 和 CSS 已经存在了这么多年,但它们仍然不支持开始和结束的基本概念。即为什么不添加 padding-start (即 ltr 上的 padding-left 和 trl 上的 padding-right )和 padding-end 等等到名称中包含 left 或 right 的任何 css...
【解决方案2】:

现在在 CSS 规范中提出了一个解决方案:逻辑属性。基本上,浏览器不会基于其他元素的 dir 属性应用不同的属性值,而是将开始具有方向感知的属性值。

所以在一个完美的世界里,一旦这些得到充分的支持,你就可以写:

.float-end {
  float: inline-end;
}

lots of properties 将存在这些新值,而不仅仅是浮点数。截至 2019 年 7 月,几乎所有人都支持,但 Microsoft(IE/Edge)除外。

【讨论】:

  • 这应该从第一天开始就在 css 中了......太糟糕了,它仍然说“这是一个实验性 API,不应该在生产代码中使用。”在您提供的链接中的所有这些属性上。通常我会留下最初接受的答案,只是增加这个答案以保留原始解决方案的原始功劳。但既然这是我自己的解决方案 - 为什么不......我会接受这个解决方案,希望它很快就会成为一个可行的生产解决方案。
【解决方案3】:

好吧,我无法为您的第一个问题(关于浮动)提供解决方案,但我可以为您提供关于第二个问题(左/右属性)的解决方案。

如 w3c 所述

如果'left'和'right'都不是'auto',则位置是 过度约束,其中之一必须被忽略。如果 包含块的“direction”属性是“ltr”,其值为 'left' 获胜,'right' 变成 -'left'。如果“方向”的 包含块是'rtl','right'获胜,'left'被忽略。

【讨论】:

  • 有趣。但这对我没有帮助(当然不是你的错),因为有时 dir 是 ltr 但你仍然想为 right: 而不是 left: 分配一个值。
【解决方案4】:

好的。 因此,了解到我所期望的不起作用(至少截至目前 [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 }
  )
}

所以在某些 SELECTOR 上使用 .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 标签上。

那个 siad,如果出于某种荒谬的原因,我将来会到达某个时间点,当我不得不更改目录两次以上时,我可以使用相同的方法并添加对 body[dir="ltr"] [dir="rtl"] [dir="ltr"] &amp; 的处理等等.. .

几年后运气好的话,有人会明白添加startend 的语义很重要,它们在LTR 上下文中分别解释为leftright,在TRL 上下文中反之亦然使我所有的宏变得多余... [例如已经在 text-align 中完成]。

【讨论】:

    【解决方案5】:

    我知道这是一个很晚的回复,但如果我的问题正确,它可以帮助某人。

    这有意义吗?

    [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 here

    【讨论】:

    • hmmm... 起初我认为这很好,但转念一想我认为这是错误的。例如,我相信第一个选择器不适用于具有“float-end”类的元素,该类位于具有 dir=ltr 属性的元素内,并且在 dir=rtl 之间没有其他元素,而是具有“float”的元素-end” 类,它位于具有 dir=ltr 属性的元素内,并且在其间至少有一个不具有 dir=rtl 属性的元素。例如它会错误地匹配 p[dir=ltr] p[dir=rtl] div div[class=float-end] 并使最后一个 div 向右浮动而不是向左浮动。
    • 如果您能提供一个带有一些 HTML 标记的真实示例,那就太好了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多