【问题标题】:Can I use a :before or :after pseudo-element on an input field?我可以在输入字段上使用 :before 或 :after 伪元素吗?
【发布时间】:2020-07-08 10:40:36
【问题描述】:

我试图在input 字段上使用:after CSS 伪元素,但它不起作用。如果我将它与span 一起使用,它可以正常工作。

<style type="text/css">
.mystyle:after {content:url(smiley.gif);}
.mystyle {color:red;}
</style>

这行得通(把笑脸放在“buu!”和“更多”之前)

<span class="mystyle">buuu!</span>a some more

这不起作用 - 它只会将 someValue 涂成红色,但没有笑脸。

<input class="mystyle" type="text" value="someValue">

我做错了什么?我应该使用另一个伪选择器吗?

注意:我不能在我的input 周围添加span,因为它是由第三方控件生成的。

【问题讨论】:

  • 如果您完全无法控制 HTML,请尝试更改 inputborder-color。我发现它更引人注目。

标签: html css pseudo-element css-content


【解决方案1】:

带有 after 和 before 的切换器示例 只需将您的输入包装在 div 块上

.fm-form-control {
  position: relative;
  margin-top: 25px;
  margin-bottom: 25.2px;
}


.fm-switcher {
  display: none;
}
.fm-switcher:checked + .fm-placeholder-switcher:after {
  background-color: #94c6e7;
}
.fm-switcher:checked + .fm-placeholder-switcher:before {
  left: 24px;
}
.fm-switcher[disabled] + .fm-placeholder-switcher {
  cursor: not-allowed;
}
.fm-switcher[disabled] + .fm-placeholder-switcher:before {
  background-color: #cbd0d3;
}
.fm-switcher[disabled] + .fm-placeholder-switcher:after {
  background-color: #eaeded;
  border-color: #cbd0d3;
}

.fm-placeholder-switcher {
  padding-left: 53px;
  cursor: pointer;
  line-height: 24px;
}
.fm-placeholder-switcher:before {
  position: absolute;
  content: '';
  left: 0;
  top: 50%;
  width: 20px;
  height: 20px;
  margin-top: -10px;
  margin-left: 2px;
  background-color: #2980b9;
  z-index: 2;
  -moz-transition: all 0.15s ease-in-out;
  -o-transition: all 0.15s ease-in-out;
  -webkit-transition: all 0.15s ease-in-out;
  transition: all 0.15s ease-in-out;
  border-radius: 12px;
}
.fm-placeholder-switcher:after {
  position: absolute;
  content: '';
  left: 0;
  top: 50%;
  width: 48px;
  height: 20px;
  margin-top: -12px;
  background-color: #ffffff;
  z-index: 1;
  border-radius: 12px;
  border: 2px solid #bdc3c7;
  -moz-transition: all 0.15s ease-in-out;
  -o-transition: all 0.15s ease-in-out;
  -webkit-transition: all 0.15s ease-in-out;
  transition: all 0.15s ease-in-out;
}
<div class='fm-form-control'>
  <input class='fm-switcher' id='switcher_id' type='checkbox'>
  <label class='fm-placeholder-switcher' for='switcher_id'>
    Switcher
  </label>
</div>

【讨论】:

    【解决方案2】:

    虽然指出 Firefox 不允许 ::after 和 ::before 内容用于无法显示任何内容的元素的行为的解释是完全正确的,但它似乎仍然可以很好地使用此规则:

    input[type=checkbox] {
        -moz-appearance: initial;
    }
    

    由于 ::after 是重新设置复选框或单选框样式的唯一方法引入更多且不相关的标记(如尾随跨度或标签),我认为强制 Firefox 允许 ::before 和::在显示内容之后,尽管没有规范。

    【讨论】:

      【解决方案3】:

      这里最大的误解是beforeafter这两个词的含义。它们不是引用元素本身,而是引用元素中的内容。所以element:before 在内容之前,element:after 在内容之后,但两者都在原始元素内。

      input 元素在 CSS 视图中没有内容,因此也没有 :before:after 伪内容。许多其他无效或替换元素也是如此。

      没有伪元素引用在元素之外

      在不同的宇宙中,这些伪元素可能被称为其他东西以使这种区别更加清晰。甚至可能有人提出了一个真正在元素之外的伪元素。到目前为止,在这个宇宙中还不是这样。

      【讨论】:

      • 我可能不明白你的意思,但如果我明白了,伪元素对 hr 有效吗? jsfiddle.net/demetriad/o49yn5hq
      • @Chris 这对我来说是一个惊喜,在搜索时,对其他一些人来说。我认为这是一个怪癖。从 CSS 的角度来看,hr 一直是模棱两可的,尽管您在讨论颜色时会看到更多。
      【解决方案4】:

      :after:before 等伪元素仅适用于容器元素。像&lt;input/&gt;&lt;img&gt; 等在一个地方开始和结束的元素不是容器元素,因此不支持伪元素。一旦您将伪元素应用于容器元素,例如&lt;div&gt;,并且如果您检查代码(见图),您就可以理解我的意思。实际上,伪元素是在容器元素内创建的。在&lt;input&gt;&lt;img&gt; 的情况下这是不可能的

      【讨论】:

        【解决方案5】:

        纯 CSS 中的可行解决方案:

        诀窍是假设在文本字段之后有一个 dom 元素。

        /*
         * The trick is here:
         * this selector says "take the first dom element after
         * the input text (+) and set its before content to the
         * value (:before).
         */
        input#myTextField + *:before {
          content: "?";
        } 
        <input id="myTextField" class="mystyle" type="text" value="someValue" />
        <!--
          There's maybe something after a input-text
          Does'nt matter what it is (*), I use it.
          -->
        <span></span>

        (*) 有限的解决方案,但是:

        • 你必须希望有以下 dom 元素,
        • 您必须希望您的输入字段后面没有其他输入字段。

        但在大多数情况下,我们知道我们的代码,所以这个解决方案看起来很高效,并且 100% 使用 CSS 和 0% jQuery。

        【讨论】:

        • input#myTextField ~ span:before { 好多了,但是 span 应该有一个更明确的类,比如 .tick.icon
        • @Val 该选择器无法正常工作,因为~ 选择了 每个 前面的元素,但您只想要第一个。
        【解决方案6】:

        :before:after 应用于容器内,这意味着您可以将其用于带有结束标记的元素。

        它不适用于自闭合元素。

        附带说明,自动关闭的元素(例如 img/hr/input)也称为“替换元素”,因为它们被替换为各自的内容。 “外部对象”缺乏更好的术语。更好的阅读here

        【讨论】:

          【解决方案7】:

          :before:after 仅适用于可以有子节点的节点,因为它们将新节点作为第一个或最后一个节点插入。

          【讨论】:

            【解决方案8】:

            我使用background-image 为必填字段创建了红点。

            input[type="text"][required] {
              background-image: radial-gradient(red 15%, transparent 16%);
              background-size: 1em 1em;
              background-position: top right;
              background-repeat: no-repeat
            }
            

            View on Codepen

            【讨论】:

            • 这真是太棒了,干得好!
            【解决方案9】:

            总结

            它不适用于&lt;input type="button"&gt;,但它适用于&lt;input type="checkbox"&gt;

            小提琴http://jsfiddle.net/gb2wY/50/

            HTML

            <p class="submit">
                <input id="submit-button" type="submit" value="Post">
                <br><br>
                <input id="submit-cb" type="checkbox" checked>
            </p>
            

            CSS

            #submit-button::before,
            #submit-cb::before {
                content: ' ';
                background: transparent;
                border: 3px solid crimson;
                display: inline-block;
                width: 100%;
                height: 100%;
                padding: 0;
                margin: -3px -3px;
            }
            

            【讨论】:

              【解决方案10】:

              :before:after 在容器内渲染

              不能包含其他元素。


              伪元素只能在容器元素上定义(或者说只支持)。因为它们的呈现方式是 within 容器本身作为子元素。 input 不能包含其他元素,因此它们不受支持。另一方面,button 也是支持它们的表单元素,因为它是其他子元素的容器。

              如果你问我,如果某些浏览器确实在非容器元素上显示这两个伪元素,这是一个错误和非标准一致性。规范直接讲元素内容...

              W3C 规范

              如果我们仔细阅读the specification,它实际上是说它们被插入inside一个包含元素:

              作者使用 :before 和 :after 伪元素指定生成内容的样式和位置。正如它们的名字所示,:before 和 :after 伪元素指定了元素文档树内容之前和之后的内容位置。 'content' 属性与这些伪元素一起指定插入的内容。

              看到了吗? 元素的文档树内容。据我了解,这意味着容器中。

              【讨论】:

              • +1 比公认的答案好得多。感谢您对标准本身的清晰解释。 [required]::before { content "*"; color: red; } 就这么多:P
              • 提示:如果您在提交输入时遇到问题,例如 &lt;input type="submit" value="Send"/&gt;,请改用 &lt;button type="submit"&gt;Send&lt;/button&gt;。演示文稿是相同的,但 &lt;button&gt; 是一个容器,因此支持 :before:after
              • &lt;hr /&gt; 怎么样?我以为它不是容器元素,但它可以渲染:after:before jsfiddle.net/Uf88j/1
              • @deathlock:这确实很有趣。我会说它一定是某种异常,我不会依赖它跨浏览器或跨版本工作...... HR 不是容器元素,因此不应允许伪元素。甚至W3C standard 也表示它允许no 内容。如果你检查 void elementcan see 这些元素在任何情况下都不应该有任何内容。伪元素是内容,因此预计未来的浏览器版本将无法显示它们。
              • ":before 和 :after 在容器内渲染" :before 和 :after 伪元素出现在“内容之前和之后”。不是“在容器的开头或结尾”。 规范没有提到容器。使用ph1 之类的标签,内容在标签内,因此之前/之后也会出现在标签内。对于像inputhr 这样的元素,:before 和:after 仍会出现在内容之前或之后,但不涉及容器(尤其是input)。 input:checked:before 广泛用于指示通过 css 选中的复选框。
              【解决方案11】:

              尝试下一个:

              label[for="userName"] {
                position: relative;
              }
              
              label[for="userName"]::after {
                content: '[after]';
                width: 22px;
                height: 22px;
                display: inline-block;
                position: absolute;
                right: -30px;
              }
              <label for="userName">
              	Name: 
              	<input type="text" name="userName" id="userName">
              	</label>

              【讨论】:

                【解决方案12】:

                正如其他人解释的那样,inputs 有点被替换为 void 元素,因此大多数浏览器不允许您在其中生成 ::before::after 伪元素。

                但是,CSS 工作组正在考虑明确允许 ::before::after,以防 input 具有 appearance: none

                来自https://lists.w3.org/Archives/Public/www-style/2016Mar/0190.html

                Safari 和 Chrome 都允许在其表单输入中使用伪元素。 其他浏览器没有。我们考虑删除它,但是 use-counter 正在记录使用它的页面的 ~.07%,这是我们最大值的 20 倍 移除阈值。

                实际上在输入上指定伪元素需要指定 输入的内部结构至少在某种程度上,我们还没有 设法做到了(我不相信我们*可以*做到)。但是鲍里斯 建议,在其中一个错误线程中,允许它出现:无 输入 - 基本上只是将它们变成

                ,而不是 “有点替换”的元素。

                【讨论】:

                  【解决方案13】:

                  Here's another approach(假设您可以控制 HTML):在输入之后添加一个空的&lt;span&gt;&lt;/span&gt;,并在 CSS 中使用input.mystyle + span:after 定位它

                  .field_with_errors {
                    display: inline;
                    color: red;
                  }
                  .field_with_errors input+span:after {
                    content: "*"
                  }
                  <div class="field_with_errors">Label:</div>
                  <div class="field_with_errors">
                    <input type="text" /><span></span> 
                  </div>

                  我在 AngularJS 中使用这种方法,因为它会自动将 .ng-invalid 类添加到 &lt;input&gt; 表单元素和表单,但不会添加到 &lt;label&gt;

                  【讨论】:

                  • 它允许添加悬停动作,例如:input:hover+span:after{color: blue}。点赞。
                  • 为什么这个答案的赞成票这么少?我认为理论知识很重要,但这解决了问题。
                  • 解决问题的好选择。
                  【解决方案14】:

                  如果您尝试使用 :before 和 :after 设置输入元素的样式,那么您很可能是在尝试模仿 CSS 堆栈中其他 span、div 甚至元素的效果。

                  正如 Robert Koritnik 的回答所指出的,:before 和 :after 只能应用于容器元素,而输入元素不是容器。

                  不过,HTML 5 引入了 button 元素,它是一个容器,其行为类似于 input[type="submit|reset"] 元素。

                      <style>
                      .happy:after { content:url(smiley.gif); }
                      </style>
                  
                      <form>
                      <!-- won't work -->
                      <input class="happy" type="submit" value="Submit" />
                  
                      <!-- works -->
                      <button class="happy">Submit</button>
                      </form>
                  

                  【讨论】:

                  • HTML 4 实际上引入了
                  【解决方案15】:

                  :after:before 在 Internet Explorer 7 及更低版本中的任何元素上均不受支持。

                  它也不适用于替换元素,例如表单元素(输入)和图像元素

                  换句话说,使用纯 CSS 不可能

                  但是,如果使用jquery,您可以使用

                  $(".mystyle").after("add your smiley here");
                  

                  API docs on .after

                  使用 javascript 附加您的内容。这适用于所有浏览器。

                  【讨论】:

                  • Alex,我使用的是 IE8 和最新的 FF,所以 IE7 不是问题。我正在寻找任何关于 :after 限制的文档,但找不到它。 w3.org/TR/CSS2/generate.html 声明,它被插入到文档树中的当前节点之后,因此它应该适用于两种情况。
                  • 除非您构建的页面仅供您自己使用,大部分互联网仍然使用这些浏览器。 w3c 规范说是的;但众所周知,浏览器实现了自己对规范的解释。在输入上使用 :after 只能在 Opera 9+ 中使用,但不能在 IE、FF、safari 或 chrome 中实现,因为它们在内部构建 DOM 的方式 - 同样不能用纯 CSS 完成。
                  • 我不确定 4 月份是否是这种情况,但 Webkit 确实支持 :after,尽管它不支持 :before:after 输入。跨度>
                  • 据我了解 W3C :after:before 伪元素只能放在容器元素上。为什么?因为它们被附加在该特定元素的内部中。 input 不是容器。例如button,因此您可以戴上它们。按预期工作。规范实际上说:在一个元素的文档树内容之前和之后它明确地说CONTENT。所以一个元素必须是一个容器。
                  • 下一个答案要好得多.. 给出实际理由而不是谈论 IE 7(谁在乎)和 jQuery(坏主意)
                  【解决方案16】:

                  您不能在输入元素中放置伪元素,但可以在阴影元素中放置,例如占位符!

                  input[type="text"] {   
                    &::-webkit-input-placeholder {
                      &:before {
                        // your code
                      }
                    }
                  }
                  

                  要使其在其他浏览器中运行,请在不同的选择器中使用:-moz-placeholder::-moz-placeholder:-ms-input-placeholder。无法对选择器进行分组,因为如果浏览器无法识别选择器,则整个语句无效。

                  更新:以上代码仅适用于 CSS 预处理器(SASS、LESS...),不使用预处理器:

                  input[type="text"]::-webkit-input-placeholder:before { // your code }
                  

                  【讨论】:

                  • 不错!请注意,占位符伪元素的属性支持有限:颜色、背景、字间距、字母间距、文本装饰、垂直对齐、文本转换、行高、文本缩进、不透明度。见css-tricks.com/almanac/selectors/p/placeholder
                  • 感谢您的提示。请记住,当用户填写输入框时,伪元素内的所有内容都会消失。如果你想要的只是像我一样显示glyphicon-search 而不触及标记,那就是用户体验问题。
                  • 关于为什么这不再有效的一些背景:bugs.chromium.org/p/chromium/issues/detail?id=582301
                  【解决方案17】:

                  我发现你可以这样做:

                  .submit .btn input
                  {
                     padding:11px 28px 12px 14px;
                     background:#004990;
                     border:none;
                      color:#fff;
                  }
                  
                   .submit .btn
                   {
                       border:none;
                       color:#fff;
                       font-family: 'Open Sans', sans-serif;
                       font-size:1em;
                       min-width:96px;
                       display:inline-block;
                       position:relative;
                   }
                  
                  .submit .btn:after
                  {
                      content:">";
                      width:6px;
                      height:17px;
                      position:absolute;
                      right:36px;
                      color:#fff;
                      top:7px;
                  }
                  <div class="submit">
                    <div class="btn">
                       <input value="Send" type="submit" />
                    </div>
                  </div>

                  您需要有一个 div 父级来接受填充和 :after。 第一个 parent 需要是相对的,第二个 div 应该是绝对的,这样您就可以设置 after 的位置。

                  【讨论】:

                    【解决方案18】:

                    您必须在输入周围使用某种包装器才能使用 before 或 after 伪元素。这是一个小提琴,它在输入的包装器 div 上有一个 before,然后将 before 放在输入中 - 或者至少看起来像它。显然,这是一种解决方法,但在紧要关头有效,并且有助于响应。如果您需要添加一些其他内容,您可以轻松地将其作为后续内容。

                    工作小提琴

                    输入中的美元符号作为伪元素:http://jsfiddle.net/kapunahele/ose4r8uj/1/

                    HTML:

                    <div class="test">
                        <input type="text"></input>
                    </div>
                    

                    CSS:

                    input {
                        margin: 3em;
                        padding-left: 2em;
                        padding-top: 1em;
                        padding-bottom: 1em;
                        width:20%; 
                    }
                    
                    
                    .test {
                        position: relative;
                        background-color: #dedede;
                        display: inline;
                    }
                    
                    .test:before {
                        content: '$';
                        position: absolute;
                        top: 0;
                        left: 40px;
                        z-index: 1;
                    }
                    

                    【讨论】:

                    • 不错的技巧,但您可以制作一个风格化的 div 以“继续”输入。看到这个小提琴jsfiddle.net/ose4r8uj/31 但你也可以使用引导程序更容易做到这一点:getbootstrap.com/css/#forms-control-validation 寻找“带有可选图标”部分。尽管如此,这与原始问题无关。
                    • 仅供参考,对于输入的 :focus、:hover 等没有好处,因为您无法定位父元素
                    【解决方案19】:

                    奇怪的是,它适用于某些类型的输入。 至少在 Chrome 中,

                    <input type="checkbox" />
                    

                    工作正常,和

                    一样
                    <input type="radio" />
                    

                    只是type=text 和其他一些不起作用。

                    【讨论】:

                    • @ANeves,它适用于我的 Chromium,但不适用于 Firefox。
                    【解决方案20】:

                    根据 CSS 2.1 规范中的 note,该规范“没有完全定义 :before 和 :after 与替换元素(例如 HTML 中的 IMG)的交互。这将在未来的规范中更详细地定义。”虽然input不再是真正的被替换元素,但基本情况并没有改变::before:after对它的影响是不确定的,一般是没有影响的。

                    解决方案是找到一种不同的方法来解决您试图以这种方式解决的问题。将生成的内容放入文本输入控件会非常误导:对用户来说,它似乎是控件中初始值的一部分,但它不能被修改——所以它似乎是在开始时强制执行的。控件,但它不会作为表单数据的一部分提交。

                    【讨论】:

                    • 这是一个评论,而不是一个答案——一个相当长的评论,但仍然是一个评论。
                    • @Blazemonger,目前还不太清楚问题是什么,但无论如何,这个答案解决了与公认答案相同的问题,但方式更正确。将生成的内容用于input 元素并非不可能,只是未指定且取决于浏览器。
                    【解决方案21】:

                    我发现这篇文章是因为我遇到了同样的问题,这是对我有用的解决方案。与替换输入的值相反,只需将其删除并在其后面绝对放置一个相同大小的跨度,跨度可以使用您选择的图标字体应用:before 伪类。

                    <style type="text/css">
                    
                    form {position: relative; }
                    .mystyle:before {content:url(smiley.gif); width: 30px; height: 30px; position: absolute; }
                    .mystyle {color:red; width: 30px; height: 30px; z-index: 1; position: absolute; }
                    </style>
                    
                    <form>
                    <input class="mystyle" type="text" value=""><span class="mystyle"></span>
                    </form>
                    

                    【讨论】:

                    • +1 -- 如果您使用的插件或框架会自动将验证类添加到元素本身而不是父标签,则此解决方案非常有效。
                    猜你喜欢
                    • 2011-12-05
                    • 2012-08-20
                    • 2013-02-05
                    • 2013-11-04
                    相关资源
                    最近更新 更多