Related
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.
: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.
:after and :before are not supported in Internet Explorer 7 and under, on any elements.
It's also not meant to be used on replaced elements such as form elements (inputs) and image elements.
In other words it's impossible with pure CSS.
However if using jquery you can use
$(".mystyle").after("add your smiley here");
API docs on .after
To append your content with javascript. This will work across all browsers.
Oddly, it works with some types of input.
At least in Chrome,
<input type="checkbox" />
works fine, same as
<input type="radio" />
It's just type=text and some others that don't work.
Here's another approach (assuming you have control of the HTML): add an empty <span></span> right after the input, and target that in CSS using 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>
I'm using this approach in AngularJS because it will add .ng-invalid classes automatically to <input> form elements, and to the form, but not to the <label>.
: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
I used the background-image to create the red dot for required fields.
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
The biggest misunderstanding here is the meaning of the words before and after. They do not refer to the element itself, but to the content in the element. So element:before is before the content, and element:after is after the content, but both are still inside the original element.
The input element has no content in the CSS view, and so has no :before or :after pseudo content. This is true of many other void or replaced elements.
There is no pseudo element referring to outside the element.
In a different universe, these pseudo elements might have been called something else to make this distinction clearer. And someone might even have proposed a pseudo element which is genuinely outside the element. So far, this is not the case in this universe.
Pseudo elements like :after, :before are only for container elements. Elements starting and closing in a single place like <input/>, <img> etc are not container elements and hence pseudo elements are not supported. Once you apply a pseudo element to container element like <div> and if you inspect the code(see the image) you can understand what I mean. Actually the pseudo element is created inside the container element. This is not possible in case of <input> or <img>
You can't put a pseudo element in an input element, but can put in shadow element, like a placeholder!
input[type="text"] {
&::-webkit-input-placeholder {
&:before {
// your code
}
}
}
To make it work in other browsers, use :-moz-placeholder, ::-moz-placeholder and :-ms-input-placeholder in different selectors. Can't group the selectors, because if a browser doesn't recognize the selector invalidates the entire statement.
UPDATE: The above code works only with CSS pre-processor (SASS, LESS...), without pre-processors use:
input[type="text"]::-webkit-input-placeholder:before { // your code }
A working solution in pure CSS:
The trick is to suppose there's a dom element after the text-field.
/*
* 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>
(*) Limited solution, though:
you have to hope that there's a following dom element,
you have to hope no other input field follows your input field.
But in most cases, we know our code so this solution seems efficient and 100% CSS and 0% jQuery.
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>
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.
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.
You have to have some kind of wrapper around the input to use a before or after pseudo-element. Here's a fiddle that has a before on the wrapper div of an input and then places the before inside the input - or at least it looks like it. Obviously, this is a work around but effective in a pinch and lends itself to being responsive. You can easily make this an after if you need to put some other content.
Working Fiddle
Dollar sign inside an input as a pseudo-element: http://jsfiddle.net/kapunahele/ose4r8uj/1/
The HTML:
<div class="test">
<input type="text"></input>
</div>
The 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;
}
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>
The question mentions "input field". Although I believe the OP was referring to input field with type=text, ::after and ::before pseudocontent does render for several different types of input fields:
input::before {
content: "My content" /* 11 different input types will render this */
}
Here is a comprehensive demo of all input types, clearly showing which ones are compatible with (in this case) the ::before pseudoelement.
To summarize, this is a list of all of the input types that can render pseudocontent:
checkbox
color
date
datetime-local
file
image
month
radio
range
time
week
If you are trying to style an input element with :before and :after, odds are you are trying to mimic the effects of other span, div, or even a elements in your CSS stack.
As Robert Koritnik's answer points out, :before and :after can only be applied to container elements and input elements are not containers.
HOWEVER, HTML 5 introduced the button element which is a container and behaves like an input[type="submit|reset"] element.
<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>
:before and :after only works for nodes that can have child nodes since they insert a new node as the first or last node.
I found that you can do it like this:
.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>
You need to have a div parent that takes the padding and the :after.
The first parent needs to be relative and the second div should be absolute so you can set the position of the after.
Summary
It does not work with <input type="button">, but it works fine with <input type="checkbox">.
Fiddle: 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;
}
While the explanations that point out that the Firefox behavior of not allowing ::after and ::before content for elements that can't display any content are quite correct, it still seems to work perfectly fine with this rule:
input[type=checkbox] {
-moz-appearance: initial;
}
As ::after is the only way to restyle a checkbox or radiobox without introducing more and unrelated markup like a trailing span or label, I think it's fine to force Firefox to allow ::before and ::after content to be displayed, despite not being to spec.
Example of switcher with after and before
just wrap your input on div block
.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>
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.
: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.
:after and :before are not supported in Internet Explorer 7 and under, on any elements.
It's also not meant to be used on replaced elements such as form elements (inputs) and image elements.
In other words it's impossible with pure CSS.
However if using jquery you can use
$(".mystyle").after("add your smiley here");
API docs on .after
To append your content with javascript. This will work across all browsers.
Oddly, it works with some types of input.
At least in Chrome,
<input type="checkbox" />
works fine, same as
<input type="radio" />
It's just type=text and some others that don't work.
Here's another approach (assuming you have control of the HTML): add an empty <span></span> right after the input, and target that in CSS using 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>
I'm using this approach in AngularJS because it will add .ng-invalid classes automatically to <input> form elements, and to the form, but not to the <label>.
: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
I used the background-image to create the red dot for required fields.
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
The biggest misunderstanding here is the meaning of the words before and after. They do not refer to the element itself, but to the content in the element. So element:before is before the content, and element:after is after the content, but both are still inside the original element.
The input element has no content in the CSS view, and so has no :before or :after pseudo content. This is true of many other void or replaced elements.
There is no pseudo element referring to outside the element.
In a different universe, these pseudo elements might have been called something else to make this distinction clearer. And someone might even have proposed a pseudo element which is genuinely outside the element. So far, this is not the case in this universe.
Pseudo elements like :after, :before are only for container elements. Elements starting and closing in a single place like <input/>, <img> etc are not container elements and hence pseudo elements are not supported. Once you apply a pseudo element to container element like <div> and if you inspect the code(see the image) you can understand what I mean. Actually the pseudo element is created inside the container element. This is not possible in case of <input> or <img>
You can't put a pseudo element in an input element, but can put in shadow element, like a placeholder!
input[type="text"] {
&::-webkit-input-placeholder {
&:before {
// your code
}
}
}
To make it work in other browsers, use :-moz-placeholder, ::-moz-placeholder and :-ms-input-placeholder in different selectors. Can't group the selectors, because if a browser doesn't recognize the selector invalidates the entire statement.
UPDATE: The above code works only with CSS pre-processor (SASS, LESS...), without pre-processors use:
input[type="text"]::-webkit-input-placeholder:before { // your code }
A working solution in pure CSS:
The trick is to suppose there's a dom element after the text-field.
/*
* 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>
(*) Limited solution, though:
you have to hope that there's a following dom element,
you have to hope no other input field follows your input field.
But in most cases, we know our code so this solution seems efficient and 100% CSS and 0% jQuery.
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>
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.
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.
You have to have some kind of wrapper around the input to use a before or after pseudo-element. Here's a fiddle that has a before on the wrapper div of an input and then places the before inside the input - or at least it looks like it. Obviously, this is a work around but effective in a pinch and lends itself to being responsive. You can easily make this an after if you need to put some other content.
Working Fiddle
Dollar sign inside an input as a pseudo-element: http://jsfiddle.net/kapunahele/ose4r8uj/1/
The HTML:
<div class="test">
<input type="text"></input>
</div>
The 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;
}
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>
The question mentions "input field". Although I believe the OP was referring to input field with type=text, ::after and ::before pseudocontent does render for several different types of input fields:
input::before {
content: "My content" /* 11 different input types will render this */
}
Here is a comprehensive demo of all input types, clearly showing which ones are compatible with (in this case) the ::before pseudoelement.
To summarize, this is a list of all of the input types that can render pseudocontent:
checkbox
color
date
datetime-local
file
image
month
radio
range
time
week
If you are trying to style an input element with :before and :after, odds are you are trying to mimic the effects of other span, div, or even a elements in your CSS stack.
As Robert Koritnik's answer points out, :before and :after can only be applied to container elements and input elements are not containers.
HOWEVER, HTML 5 introduced the button element which is a container and behaves like an input[type="submit|reset"] element.
<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>
:before and :after only works for nodes that can have child nodes since they insert a new node as the first or last node.
I found that you can do it like this:
.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>
You need to have a div parent that takes the padding and the :after.
The first parent needs to be relative and the second div should be absolute so you can set the position of the after.
Summary
It does not work with <input type="button">, but it works fine with <input type="checkbox">.
Fiddle: 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;
}
While the explanations that point out that the Firefox behavior of not allowing ::after and ::before content for elements that can't display any content are quite correct, it still seems to work perfectly fine with this rule:
input[type=checkbox] {
-moz-appearance: initial;
}
As ::after is the only way to restyle a checkbox or radiobox without introducing more and unrelated markup like a trailing span or label, I think it's fine to force Firefox to allow ::before and ::after content to be displayed, despite not being to spec.
Example of switcher with after and before
just wrap your input on div block
.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>
in the code:
<!DOCTYPE html>
<html>
<head>
<style>
.parent {
position: absolute;
top:500px;
width:400px;
border:1px solid green;
}
.parent:before {
z-index:-1;
content:'';
position:absolute;
opacity:0.5;
width:400px;
height:200px;
background-image:url('wallpaper324845.jpg');
border:1px solid red;
}
.child {
Color:black;
border:1px solid black;
}
</style>
</head>
<body>
<div class="parent">
<div class="child">Hello I am child</div>
</div>
</body>
</html>
I'm trying to create a transparent background as described in this thread: How to set opacity in parent div and not affect in child div?.
Looking at the code from the 4th answer. How does this work, I'm confused with the use of .parent and .parent:before. I would think that this would create a .parent:before element before every parent element. Really confused how does this work?
:before creates a virtual content using CSS, so in the above case, author uses below snippet means
.parent:before{
z-index:-1;
content:'';
position:absolute;
opacity:0.5;
width:400px;
height:200px;
background-image:url('wallpaper324845.jpg');
border:1px solid red;
}
He is creating a virtual element using :before, which he then positions absolute, assigns some dimensions, and assigns the background, to make sure that it stays below the div content, he uses z-index: -1;
In other words, :before, :after are nothing but assume nesting two span elements inside your div, but by using pseudo elements, you don't need to have span as you can achieve the same thing with the pseudo elements.
Consider you have something like this
<div>
Hello
<span></span>
</div>
div {
position: relative;
}
div span {
position: absolute;
width: 100%;
height: 100%;
background: #f00;
z-index: -1;
left: 0;
top: 0;
}
Demo
Can be also achieved using :before or :after, markup stays the same but CSS goes like
div {
position: relative;
}
div:after {
content: "";
position: absolute;
width: 100%;
height: 100%;
background: #f00;
z-index: -1;
left: 0;
top: 0;
}
Demo
So, it just saves you one empty element in your HTML, but if you look at the above CSS, am using content property which is ALWAYS associated with :before or :after, and yes, it is required, even if you keep it blank.
Also, note that :before and :after generated content are inline, so inorder to make height, width work, you need to explicitly mention display: block; or display: inline-block; if you want to make it block level, but in this particular case, you won't need that as the pseudo element is positioned absolute
div:after {
content: "Hello";
margin-top: 20px; /* This wont work as pseudo is inline by default */
}
Demo
So make it block or inline-block
Demo
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.
Below is a document tree with HTML as root.
HTML
.HEAD
..TITLE
.BODY
..H1
..P
..UL
...LI
...LI
...LI
For example, the following rule inserts the string "Note: " before the content of every P element whose "class" attribute has the value "note":
p.note:before { content: "Note: " }
The formatting objects (e.g., boxes) generated by an element include generated content. So, for example, changing the above style sheet to:
p.note:before { content: "Note: " }
p.note { border: solid green }
would cause a solid green border to be rendered around the entire paragraph, including the initial string.
The :before and :after pseudo-elements inherit any inheritable properties from the element in the document tree to which they are attached.
For example, the following rules insert an open quote mark before every Q element. The color of the quote mark will be red, but the font will be the same as the font of the rest of the Q element:
q:before {
content: open-quote;
color: red
}
In a :before or :after pseudo-element declaration, non-inherited properties take their initial values.
So, for example, because the initial value of the 'display' property is 'inline', the quote in the previous example is inserted as an inline box (i.e., on the same line as the element's initial text content). The next example explicitly sets the 'display' property to 'block', so that the inserted text becomes a block:
body:after {
content: "The End";
display: block;
margin-top: 2em;
text-align: center;
}
The :before and :after pseudo-elements elements interact with other boxes, such as run-in boxes, as if they were real elements inserted just inside their associated element.
For example, the following document fragment and style sheet:
<h2> Header </h2> h2 { display: run-in; }
<p> Text </p> p:before { display: block; content: 'Some'; }
...would render in exactly the same way as the following document fragment and style sheet:
<h2> Header </h2> h2 { display: run-in; }
<p><span>Some</span> Text </p> span { display: block }
Similarly, the following document fragment and style sheet:
<h2> Header </h2> h2 { display: run-in; }
h2:after { display: block; content: 'Thing'; }
<p> Text </p>
...would render in exactly the same way as the following document fragment and style sheet:
<h2> Header <span>Thing</span></h2> h2 { display: block; }
span { display: block; }
<p> Text </p>
Basically, :before (like :after) is a CSS pseudo-element. So it's almost like a HTML inline element. Almost.
To play with pseudo elements, you need to give it a content property (empty string in most cases). Note that it's an inline element by default, so it can't have width / height. You need to set display: block (or inline-block, or whatever).
I think you missed to set the relative position on the parent element (.parent). There it is :
.parent{
position: relative;
top:500px;
width:400px;
border:1px solid green;
}
Try looking at this article. it explains how :before and :after pseudo selectors work:
http://coding.smashingmagazine.com/2011/07/13/learning-to-use-the-before-and-after-pseudo-elements-in-css/
Can you please let me know how I can force CSS to make the line-through property wider than element width?
For Example
<h3 style="text-decoration:line-through">50</h3>
and result looks like now how I can make the line wider than element to be more obvious?
Like
You can use which is a cheesy way to go for
<div> HELLO </div>
Demo
Or you can do is, use :before and :after pseudo with content property
Demo
div {
text-decoration:line-through;
}
div:before,
div:after {
content: "\00a0\00a0";
}
Note: Using a general selector here, consider using class or an id to target the element specifically, also, if your text is between other text, consider wrapping that in a span and than use :before and :after over span.
Briefing an answer here with solution that uses CSS Positioning techniques, using which you can also control the thickness of the strike through..
Here, am positioning the child element absolute to the parent element. So make sure you declare position: relative; on parent. Rest, :after pseudo handles the rest and also be sure that you use content: "";, though it's blank, it's mandatory.
Demo 3 (Using CSS Positioning)
div {
position: relative;
display: inline-block;
padding: 0 10px;
margin: 10px;
}
div:after {
content: "";
position: absolute;
border: 2px solid #000;
top: 50%;
margin-top: -1px;
width: 100%;
left: -2px;
}
padding: N px;
line-height: N px;
in html
Nested Div's <div><div></div></div>
In the following case, how can I make it such that the text generated by the :after is outside the box of the span? (It currently is rendered inside, i.e. it makes the span element wider)
HTML
<span class="my">Boxtext</span>
CSS
span.my {
padding: 4px 8px;
background-color: red;
display: inline-block;
border-radius: 10px;
margin-left: 20px;
}
span.my:after {
content: " text that is supposed to come after the box";
}
I guess this is somewhat similar to list-style-position, where you can chose inside or outside...
I believe CSS content is considered part of the object against which it was rendered. You could make the argument that :after should have been named :append.
For your case you can try putting an extra element inside span.my:
<span class="my"><span>Boxtext</span></span>
span.my span { ... }
span.my:after { ... }
Or styling the content specifically.
span.my:after {
content: " text that is supposed to come after the box";
background-color: white;
position: absolute;
margin-left: 10px;
}
Just use position: absolute in the ::after {} pseudo-element's css:
span.my:after {
content: " text that is supposed to come after the box";
position: absolute;
left: 100%;
}โ
Remember, of course, to use position: relative; (or any other position value) on the parent span.my element.
JS Fiddle demo.
Also remember that as the ::after (and the ::before) pseudo-element inherits from the span to which it's 'attached' that it'll inherit the width, so that may need to be explicitly overridden in the CSS for that/those elements.