根据先前内容调整 HTML span 元素的位置

Adjusting the position of an HTML span element based on prior content

这是我正在尝试处理的问题。

当有价格时 - 并且只有当有价格时,我才想附加定价货币和价格单位(如有)。通过查看下面的示例可以最好地理解这一点

#spnOldPrice{text-decoration:line-through;}
#spnNewPrice{color:red !important;}
.pricing{position:relative;}
.pricing:not(:empty)::before
{
 position:absolute;
 left:100%;
 content:attr(data-label);
}
<span id='spnOldPrice'><span id='plainoldPrice' class='pricing'>9.99</span></span>
<span id='spnNewPrice'><span id='plainnewPrice' class='pricing'>4.99</span></span>
<hr>
<span id='spnOldPrice'><span id='oldPrice' class='pricing' data-label='€/box'>9.99</span></span>
<span id='spnNewPrice'><span id='newPrice' class='pricing' data-label='€/box'>4.99</span></span>

我这里有两个例子

  1. 第一个简单地表示全价和促销价。这里没有问题。
  2. 第二个表示完整价格和促销价格以及货币和价格单位

后一个例子说明了问题。附加 €/box 字符串的存在导致我的条件 CSS 规则 :not(:empty)::before 启动,在这种情况下绝对定位的 before 伪元素显示可见内容。自然地,以下跨度——促销价——对这个伪元素一无所知,并将自己绘制在 €/box 位下。

我可以抛开我在这里做事的方式,使用多个嵌套跨度并使用一点 JS 来确保所有东西一直都能正常工作。但是,我想知道这里是否有更优雅的 CSS only 解决方案。

使用 position: absolute 将创建被覆盖的文本,如@UIDeveloper
所述 如果要在 之后 元素显示属性值,只需使用 :after :pseudo.

关于可访问性的注意事项:(也许您删除了该部分以获得关于 SO 的问题的最短代码)两种价格都将被读取到盲屏 reader用户。他们不会知道第一个被击中了。为避免这种情况,您可以添加一个只能由屏幕 readers 感知的跨度(class 已经像 .visually-hidden / .element-invisible / .sr-only在 WP、Drupal、Bootstrap 等中找到)和解释性文本:<span class="visually-hidden">Old price</span>

#spnOldPrice{text-decoration:line-through;}
#spnNewPrice{color:red !important;}
/* .pricing{position:relative;} */
.pricing:not(:empty)::after
{
 /*position:absolute;*/
 /*left:100%;*/
 content:attr(data-label);
}
<span id='spnOldPrice'><span id='plainoldPrice' class='pricing'>9.99</span></span>
<span id='spnNewPrice'><span id='plainnewPrice' class='pricing'>4.99</span></span>
<hr>
<span id='spnOldPrice'><span id='oldPrice' class='pricing' data-label='€/box'>9.99</span></span>
<span id='spnNewPrice'><span id='newPrice' class='pricing' data-label='€/box'>4.99</span></span>


变体: flexbox 允许通过附加 -reverse: flex-direction: row-reverse 从右到左(以及从下到上)显示弹性项目(有效因为伪元素被认为是弹性项目)。

#spnOldPrice{text-decoration:line-through;}
#spnNewPrice{color:red !important;}
.pricing{
  display: inline-flex;
    flex-direction: row-reverse;
    justify-content: flex-end; /* which is... left-side! */
}
.pricing:not(:empty)::after
{
 content:attr(data-label);
}
<span id='spnOldPrice'><span id='plainoldPrice' class='pricing'>9.99</span></span>
<span id='spnNewPrice'><span id='plainnewPrice' class='pricing'>4.99</span></span>
<hr>
<span id='spnOldPrice'><span id='oldPrice' class='pricing' data-label='€/box'>9.99</span></span>
<span id='spnNewPrice'><span id='newPrice' class='pricing' data-label='€/box'>4.99</span></span>

更简单的方法是在第二个跨度上添加边距:

#spnOldPrice{text-decoration:line-through;}
#spnNewPrice{color:red !important;}
.pricing{position:relative;}
.pricing:not(:empty)::before
{
 position:absolute;
 left:100%;
 content:attr(data-label);
}
#newPrice{margin-left: 40px;}
<span id='spnOldPrice'><span id='plainoldPrice' class='pricing'>9.99</span></span>
<span id='spnNewPrice'><span id='plainnewPrice' class='pricing'>4.99</span></span>
<hr>
<span id='spnOldPrice'><span id='oldPrice' class='pricing' data-label='€/box'>9.99</span></span>
<span id='spnNewPrice'><span id='newPrice' class='pricing' data-label='€/box'>4.79</span></span>