【问题标题】:Center a Pseudo Element居中伪元素
【发布时间】:2013-05-25 00:04:07
【问题描述】:

第一次真正使用伪:after 选择器。不确定我遇到的问题是它的限制还是我只是错过了一些明显的东西。

Here's my live code.

li.current:after {
    border-width: 1px 1px 0 0;
    content: ' ';
    background: #256f9e;
    display: block;
    height: 13px;
    position: absolute;
    width: 10px;
    top: 6;
    margin:0px auto;
    z-index: 99;
    transform: rotate(-224deg);
    -webkit-transform: rotate(-224deg);
    -moz-transform: rotate(-224deg);
    -ms-transform: rotate(-224deg);
    -o-transform: rotate(-224deg);
    transform-origin: 50% 50%;
    -webkit-transform-origin: 50% 50%;
    -moz-transform-origin: 50% 50%;
    -ms-transform-origin: 50% 50%;
    -o-transform-origin: 50% 50%;
    text-align: center;
    float: center;
}

我创建了一个小三角形(或者更确切地说是一个已旋转为看起来像三角形的盒子)。我希望它以<li></li> 为中心,但使用我的常规方法无法弄清楚。 失败的事情(不分先后):

text-align: center;
float: center;
margin: 0 auto;
margin-right: 0;
margin-left: 0;

我错过了什么?我怀疑这很重要,但我正在使用 AngularJS。以为我会提到它,以防 Angular 和 Pseudo 选择器之间存在已知冲突(我对此表示怀疑)。 谢谢。

【问题讨论】:

    标签: css pseudo-element


    【解决方案1】:

    问题在于您对absolute 定位的使用以及您尝试使其居中的方法。如果您绝对定位一个元素,ol' margin: 0 auto; 方法将无法使事物居中。我向您解释为什么这是在问题的末尾,但如果您只是希望它起作用,让我们先找到解决方案。

    这里有一些工作代码。 View it on JSFiddle

    #tool-menu li {
      ...
      position: relative;
    }
    
    li.current:after {
      ...
      position: absolute;
      width: 10px;
      top: 6;
      left: 50%;
      margin-left: -5px;
    }
    

    让我们分解这里发生的事情。

    设置新的包含块

    在您原来的 Fiddle 中,伪元素的位置绝对相对于视口。一个例子可能是展示这意味着什么以及为什么我们不想要这个的最佳方式。考虑将其设置为top: 0。这将使其锁定在浏览器窗口的顶部(或者,在这种情况下,JSFiddle 框架),而不是父级(li)。所以,如果我们的菜单碰巧在页面底部,或者甚至四处移动,伪元素就会独立于它浮动,粘在页面顶部。

    当您没有在任何父元素上显式设置位置时,这是绝对定位元素的默认行为。我们想要的是定义其相对于父级的位置。如果我们这样做,那么伪元素就会粘在父元素上,无论它碰巧在哪里。

    要做到这一点,您需要将父级#tool-menu li 设置为显式定位(这意味着将其设置为position: static 以外的任何内容)。如果您选择使用position: relative;,它不会更改页面上父级的计算位置,而是执行我们想要的操作。所以这就是我使用那个的原因。

    从技术角度来说,我们在这里所做的是为孩子创建一个新的containing block

    定位伪元素

    既然我们的绝对定位将相对于父级确定,我们可以利用这样一个事实,即我们可以使用百分比来定义放置子级的位置。在这种情况下,您希望它居中,所以我将其设置为 left: 50%

    不过,如果你这样做,你会看到它在 50% 处与伪元素的左边缘对齐。这不是我们想要的——我们希望伪元素的中心位于中间。这就是为什么我添加了否定的margin-left。这会使中间与父对象的中心对齐。

    一旦我们这样做,它就会居中!辉煌!

    为什么我的margin: auto; 不起作用?

    保证金的自动值是通过相当复杂的算法计算得出的。有时,它的计算结果为 0。根据经验,我知道这是发生这种情况的一个例子,尽管我还没有通过算法找到确切的原因。如果你想通过它,take a look at the spec most browsers have most likely implemented.

    【讨论】:

    • 这太棒了!没想到这会是父容器的问题。你解决了我的头痛!
    • 负的“margin-left”应该是-25%,而不是任意数量的像素。
    • @malthe 你是对的,它不应该是任意数量的像素,我选择的 -5px 也不是任意的。它正好是伪元素宽度的一半。正如您所建议的,以百分比指定的 margin-left 将基于父级的宽度,因此无法解决。您可以通过修改我上面链接的 JSFiddle 来验证这一点。即使它确实使用了伪元素的宽度,而不是父元素的宽度,它也需要为 -50%,而不是 -25%。
    • “text-align: center; transform: translate(-50%, 0);”怎么样。这似乎对我有用。
    • @malthe 如果我希望伪元素居中并覆盖 50% 的父元素,我发现使用样式属性 left: 25%width: 50% 可以。
    【解决方案2】:

    使用calc 居中

    您也可以使用 css 中的calc 函数将伪元素居中。

    注意:IE8 及更低版本 (caniuse) 不支持此功能,但您可以为旧版浏览器提供后备方案。

    code pen 上查看它。我也在使用 MarkP 的 css 边框方法来绘制三角形。

    li.current:after {
      content: '';
      display: block;
      height: 0;
      position: absolute;
      width: 0;
      overflow: hidden;
      bottom: -5px;
      left: calc(50% - 5px);
      z-index: 2;
      border-top: 5px #256f9e solid;
      border-left: 5px transparent solid;
      border-right: 5px transparent solid;
    }
    

    【讨论】:

    • 这是一件需要注意的好事情,尽管它在很多浏览器中似乎确实存在很多错误。我肯定会尝试找到后备方案并暂时谨慎使用它。我发现这篇文章非常有用:css-tricks.com/a-couple-of-use-cases-for-calc
    【解决方案3】:

    将宽度定义为百分比,使其成为块元素并在中心对齐文本不是更好吗?

    “浮动:中心;”是无效的,并且不会工作。混合浮动元素和绝对定位元素肯定会给布局带来麻烦,因为它们不能很好地协同工作。

    试试这样的:

    li.current:after {
    content: 'YOUR CONTENT';
    display: block;
    width: 100%;
    text-align: center; }
    

    【讨论】:

      【解决方案4】:

      不直接相关(已经投票支持 jmeas),但您可能会发现使用 CSS 边框技巧制作三角形更容易。例如

      li.current:after {
          content: '';
          display: block;
          height: 0;
          position: absolute;
          width: 0;
          overflow:hidden;
          bottom: 0;
          left: 50%;
          margin: 0 0 -5px -5px;
          z-index: 99;
          border-top: 5px #256f9e solid;
          border-left: 5px transparent solid;
          border-right: 5px transparent solid;
      }
      

      关于 jmeas 所建议的关于垂直定位的类似策略。我们与底部对齐,然后使用负边距底部将其推出到所需位置。

      【讨论】:

        【解决方案5】:

        使用margin:auto 居中

        只要元素声明了宽度,就可以使用绝对居中方法。

        要使用此方法,rightleft 属性必须设置为 0margin: auto 才能生效。

        此方法也可以扩展为实现水平居中。

        查看链接了解完整信息:

        http://www.smashingmagazine.com/2013/08/09/absolute-horizontal-vertical-centering-css/

        li.current:after {
          content: "";
          position: absolute;
          display: block;
          right: 0;
          bottom: -5px;
          left: 0;
          margin: auto;
          border-width: 5px;
          border-style: solid;
          border-color: transparent;
          border-top-color: #256f9e;
          width: 200px;
          height: 200px;
        }
        
        ul {
          list-style-type: none;
          padding: 0;
          margin: 0;
        }
        <div>
          <ul>
            <li class="current"></li>
          </ul>
        </div>

        【讨论】:

          【解决方案6】:

          使用伪元素 :after 或 :before 使用 display: inline-block;

          试试这样的:

          content: url(../images/no-result.png);
          display: inline-block;
          width: 100%;
          text-align: center;
          

          【讨论】:

            【解决方案7】:

            这可能是最简单的方法:

            .child_class::after{
                position: absolute;
                content: 'YourContentHere';
                width: 100%;
                text-align: center;
                top: 50%;
            }
            

            最简单的方法 -

            【讨论】:

              【解决方案8】:

              使用transform: translate() 可以在没有固定大小的情况下完成居中。这是因为translate(&lt;x&gt;%) 将使用(伪)元素自己的大小,而leftmargin-left 将使用容器的大小。因此,通过将它们一起使用,我们可以找到确切的中心点。

              tl;博士

              垂直居中:

              .container {
                position: relative;
              }
              
              .container:after {
                top: 50%;
                transform: translateY(-50%);
              }
              

              水平居中:

              .container {
                position: relative;
              }
              
              .container:after {
                left: 50%;
                transform: translateX(-50%);
              }
              

              完整示例

              .container {
                position: relative;
                display: inline-block;
                background: #4aa;
                color: white;
                padding: .5ex 1ex; 
              }
              
              .container:after {
                content: ":after";
                position: absolute;
                background: #a4a;
                color: white;
                padding: .5ex 1ex; 
              
                /* position below container */
                top: 100%;
              
                /* move right by 50% of containers width */
                left: 50%;
              
                /* move left by 50% of own width */
                transform: translateX(-50%);
              }
              <p class="container">
                Container with content
              </p>

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2016-04-10
                • 1970-01-01
                • 2013-01-09
                • 2015-06-28
                • 2020-11-19
                • 2012-02-18
                • 2015-07-15
                • 2017-04-09
                相关资源
                最近更新 更多