我可以在输入字段上使用:before或:after伪元素吗?


685

我正在尝试:afterinput字段上使用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">

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

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


如果你已经完全没有了控件的HTML,尝试改变border-colorinput吧。我发现这更引人注意。
Blazemonger,2014年

Answers:


253

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

它还不打算用于替换的元素,例如表单元素(输入)和图像元素

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

但是,如果使用jQuery,则可以使用

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

.after上的API文档

用javascript附加内容。这将适用于所有浏览器。


Alex,我正在使用IE8和最新的FF,所以IE7没问题。我正在搜索有关:after限制的任何文档,但找不到它。w3.org/TR/CSS2/generate.html指出,它被插入到文档树中的当前节点之后,因此在两种情况下都应该起作用。
matra 2010年

3
除非您仅为自己创建页面,否则仍有很大一部分互联网仍会使用这些浏览器。w3c规范说是的。但众所周知,浏览器会自行执行对规范的解释。在输入上使用:after仅在Opera 9+中有效,但由于其内部构造DOM的方式而无法在IE,FF,safari或chrome中实现-再次,纯CSS不能做到这一点。
Alex

3
我不知道,如果是这样的四月的情况下,但Webkit的不支持:after一般,虽然它不支持任何:before:after上输入。
coreyward 2010年

258
据我了解W3C :after:before伪元素,它们只能放在容器元素上。为什么?因为它们附加该特定元素内。input不是容器。button例如,因此您可以戴上它们。可以正常工作。规范实际上说:元素的文档树内容之前和之后它明确表示CONTENT。因此,元素必须是容器。
罗伯特·科里特尼克

29
下一个答案要好得多。给出实际原因,而不是谈论IE 7(谁在乎)和jQuery(坏主意)
Rowan 2014年

1302

:before:after在容器内渲染

和<input>不能包含其他元素。


伪元素只能在容器元素上定义(或者最好仅支持)。因为它们的呈现方式容器本身内作为子元素。input不能包含其他元素,因此不受支持。甲button在另一方面这也是一个表格元件支持它们,因为它的其他子元素的容器。

如果您问我,是否某个浏览器确实在非容器元素上显示了这两个伪元素,那是一个错误,并且是非标准的一致性。规范直接讨论元素的内容...

W3C规格

如果我们仔细阅读说明书,它实际上说,他们被插入含有元素:

作者使用:before和:after伪元素指定生成内容的样式和位置。顾名思义,:before和:after伪元素指定元素在文档树内容之前和之后的位置。“ content”属性与这些伪元素一起指定了要插入的内容。

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


119
+1比接受的答案好得多。感谢您对标准本身的清晰解释。这么多[required]::before { content "*"; color: red; }:P
凯文PENO

93
提示:如果仅使用提交输入时遇到问题<input type="submit" value="Send"/>,请<button type="submit">Send</button>改用。表示是相同的,但是<button>是一个容器,因此支持:before:after
流感

15
<hr />呢 我以为这不是容器元素,但是可以渲染:after:before jsfiddle.net/Uf88j/1
deathlock'deathlock

7
@deathlock:确实很有趣。我会说这一定是一种异常,并且我不会依赖它在跨浏览器或跨版本中工作... HR不是容器元素,因此不应允许使用伪元素。甚至W3C标准都说它不允许任何内容。而且,如果您检查void元素,会发现在任何情况下这些元素都不应包含任何内容。伪元素是内容,因此希望将来的浏览器版本无法显示它们。
罗伯特·科里特尼克

5
:before和:after在容器内渲染 ”:before和:after伪元素出现在“内容之前和之后 ”。不是“在容器的开头或结尾”。该规范未提及容器。使用p和标签h1,内容在标签内,因此之前/之后也将出现在标签内。使用input和元素时hr,:before和:after仍会出现在内容之前或之后,但不涉及容器(尤其是for input)。input:checked:before广泛用于指示通过CSS选中的复选框。
Radley Sustaire 2014年

60

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

<input type="checkbox" />

工作正常,与

<input type="radio" />

只是type=text和其他一些无效。


1
@ANeves,它对Chromium有用,但对Firefox不起作用。
kcpr

44

这是另一种方法(假设您可以控制HTML):<span></span>在输入之后添加一个空白,然后使用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自动将类添加到<input>表单元素和表单中,而不是添加到中<label>


1
它允许添加悬停动作,例如:input:hover+span:after{color: blue}。赞成。
krassowski

1
为什么这个答案投票很少?我认为理论知识很重要,但这可以解决问题。
jorgefpastor

解决问题的不错选择。
小丑

39

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

它不适用于自动关闭的元素。

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


这个答案是正确,简洁的,并提供了重要的上下文。应该在最上面,imo。
保罗

31

我使用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
}

在Codepen上查看


20

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

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 }

3
真好!请注意,占位符伪元素具有有限的属性支持:颜色,背景,单词间距,字母间距,文本修饰,垂直对齐,文本转换,行高,文本缩进,不透明度。参见css-tricks.com/almanac/selectors/p/placeholder
henry

感谢您的提示。只要记住,当用户填写输入框时,伪元素内的所有内容都会消失。如果像我一样,您想要的只是显示一个glyphicon-search未触摸的标记,那就是UX问题。
Davi Lima

2
关于此操作不再起作用的一些上下文:bugs.chromium.org/p/chromium/issues/detail?id=582301
奥利弗·约瑟夫·阿什

17

伪元素(如:after:before仅用于容器元素。开始和在像一个单一的地方封闭元件<input/><img>等不是容器元素,因此伪构件不被支持。将伪元素应用于容器元素后<div>,如果您检查代码(参见图片),就可以理解我的意思。实际上,伪元素是在容器元素内部创建的。在<input>或的情况下这是不可能的<img>

在此处输入图片说明


15

纯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元素,
  • 您必须希望没有其他输入字段跟随您的输入字段。

但是在大多数情况下,我们知道我们的代码,因此该解决方案似乎很有效,并且CSS的使用率为100%,jQuery的使用率为0%。


2
input#myTextField ~ span:before {要好得多,但跨度应该有一类真正更明确像.tick或者.icon
瓦尔

13

我发现这个帖子的原因是我遇到了同样的问题,这是对我有用的解决方案。与其替换输入值,不如将其删除并在其后绝对放置一个相同大小的跨度,跨度可以使用: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
+1-如果您使用的插件或框架会自动向元素本身(而不是父标签)添加验证类,则此解决方案效果很好。
Blazemonger,2014年

9

这里最大的误区,就是这些词的含义beforeafter。它们不是指元素本身,而是指元素中的内容。所以,element:before是之前的内容,并且element:after是内容之后,但两者仍然是原来的元素中。

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

没有伪元素引用元素外部

在不同的宇宙中,这些伪元素可能被称为其他名称,以使这种区分更加清晰。甚至有人可能提出了一个伪元素,而该伪元素确实在元素之外。到目前为止,在这个宇宙中情况并非如此。


我可能不明白您的意思,但是如果这样做,伪元素在hr上起作用吗?jsfiddle.net/demetriad/o49yn5hq
克里斯(Chris

1
@Chris这让我感到惊讶,也让其他人感到惊讶。我认为这很奇怪。hr从CSS的角度看,一直以来都是模棱两可的,尽管您在讨论颜色时看到的更多。
曼戈

5

根据CSS 2.1规范中的注释,该规范“并未完全定义:before和:after与替换元素(例如HTML中的IMG)的交互。这将在以后的规范中更详细地定义。” 虽然input不是真正的替换元素更多,基本态势没有改变:效果:before:after未指定就可以了,一般没有影响。

解决方案是找到一种不同的方法来解决您要解决的问题。将生成的内容放入文本输入控件中会产生很大的误导性:对用户而言,它似乎是控件中初始值的一部分,但无法修改-因此,它看起来像是在控件开始时被强制执行的操作控件,但它不会作为表单数据的一部分提交。


3
这是一个评论,而不是一个答案-相当长的评论,但仍然是评论。
Blazemonger,2014年

@Blazemonger,尚不清楚问题是什么,但是无论如何,该答案与被接受的答案都解决了相同的问题,但是以更正确的方式。将生成的内容用于元素(并非未指定且取决于浏览器)并非不可能input
Jukka K. Korpela 2014年

5

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

然而,CSS工作组正在考虑明确允许::before::after万一inputappearance: none

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

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

实际上,在输入上指定伪元素将需要至少指定输入的内部结构,而我们尚未设法做到这一点(我不确定我们可以做到)。但是鲍里斯(Boris)在其中一个bug线程中建议,允许它出现:无输入-基本上只是将它们转换为<div>,而不是“ kinda替换”元素。


4

尝试下一个:

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>


3

您必须在输入周围有某种包装,才能使用伪元素之前或之后。这是一个小提琴,它在输入的包装div上具有一个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,但您也可以使用bootstrap使其更容易:getbootstrap.com/css/#forms-control-validation查找“带有可选图标”部分。即使,这与原始问题无关。
维克多·伊文斯

1
仅供参考,对于输入的:focus,:hover等
无济于事,

2

如果尝试使用: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实际上引入了<button>元素。
李斯特先生,

1

摘要

它不能使用<input type="button">,但可以使用<input type="checkbox">

小提琴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;
}

1

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


0

我发现您可以这样做:

您需要有一个带填充和:after的div父级。第一个父级必须是相对的,第二个div应该是绝对的,以便可以设置之后的位置。


-1

我有另一个想法,用这个代替:

<div>
<input type="text"></input>text can be entered here</div>

该问题的作者明确指出,他们无法更改HTML标记。这个答案没有道理。@Morpheus可能应该被否决了,而不是被编辑了。
Palec
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.