Can I use a :before or :after pseudo-element on an

2018-12-31 00:03发布

I am trying to use the :after CSS pseudo-element on an input field, but it does not work. If I use it with a span, it works OK.

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

This works (puts the smiley after "buu!" and before "some more")

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

This does not work - it only colors someValue in red, but there is no smiley.

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

What am I doing wrong? should I use another pseudo-selector?

Note: I cannot add a span around my input, because it is being generated by a third-party control.

19条回答
孤独总比滥情好
2楼-- · 2018-12-31 00:39

try next:

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楼-- · 2018-12-31 00:42

As others explained, inputs are kinda-replaced void elements, so most browsers won't allow you to generate ::before nor ::after pseudo-elements in them.

However, the CSS Working Group is considering explicitly allowing ::before and ::after in case the input has appearance: none.

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

Safari and Chrome both allow pseudo-elements on their form inputs. Other browsers don't. We looked into removing this, but the use-counter is recording ~.07% of pages using it, which is 20x our max removal threshold.

Actually specifying pseudo-elements on inputs would require specifying the internal structure of inputs at least somewhat, which we haven't managed to do yet (and I'm not confident we *can* do). But Boris suggested, in one of the bugthreads, allowing it on appearance:none inputs - basically just turning them into <div>s, rather than "kinda-replaced" elements.

查看更多
何处买醉
4楼-- · 2018-12-31 00:43

I found this post as I was having the same issue, this was the solution that worked for me. As opposed to replacing the input's value just remove it and absolutely position a span behind it that is the same size, the span can have a :before pseudo class applied to it with the icon font of your choice.

<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>
查看更多
与风俱净
5楼-- · 2018-12-31 00:44

:before and :after are applied inside a container, which means you can use it for elements with an end tag.

It doesn't apply for self-closing elements.

On a side note, elements which are self-closing (such as img/hr/input) are also known as 'Replaced Elements', as they are replaced with their respective content. "External Objects" for the lack of a better term. A better read here

查看更多
栀子花@的思念
6楼-- · 2018-12-31 00:45

According to a note in the CSS 2.1 spec, the specification “does not fully define the interaction of :before and :after with replaced elements (such as IMG in HTML). This will be defined in more detail in a future specification.” Although input is not really a replaced element any more, the basic situation has not changed: the effect of :before and :after on it in unspecified and generally has no effect.

The solution is to find a different approach to the problem you are trying to address this way. Putting generated content into a text input control would be very misleading: to the user, it would appear to be part of the initial value in the control, but it cannot be modified – so it would appear to be something forced at the start of the control, but yet it would not be submitted as part of form data.

查看更多
琉璃瓶的回忆
7楼-- · 2018-12-31 00:47

:before and :after render inside a container

and <input> can not contain other elements.


Pseudo-elements can only be defined (or better said are only supported) on container elements. Because the way they are rendered is within the container itself as a child element. input can not contain other elements hence they're not supported. A button on the other hand that's also a form element supports them, because it's a container of other sub-elements.

If you ask me, if some browser does display these two pseudo-elements on non-container elements, it's a bug and a non-standard conformance. Specification directly talks about element content...

W3C specification

If we carefully read the specification it actually says that they are inserted inside a containing element:

Authors specify the style and location of generated content with the :before and :after pseudo-elements. As their names indicate, the :before and :after pseudo-elements specify the location of content before and after an element's document tree content. The 'content' property, in conjunction with these pseudo-elements, specifies what is inserted.

See? an element's document tree content. As I understand it this means within a container.

查看更多
登录 后发表回答