Why do I need an empty `content` property on an ::after pseudo-element?
You cannot style generated content without defining what that content should be. If you don’t really need any content, just an extra “invisible element” to style, you can set it to the empty string (content: ''
) and just style that.
It’s easy to confirm this yourself: http://jsfiddle.net/mathias/YRm5V/
By the way, the snippet you posted is the micro clearfix hack, which is explained here: http://nicolasgallagher.com/micro-clearfix-hack/
As for your second question, you’ll need an HTML5 shiv (small piece of JavaScript) to make <nav>
stylable in some older browsers.
Why do the :before and :after pseudo-elements require a 'content' property?
The reason you need a content: ''
declaration for each ::before
and/or ::after
pseudo-element is because the initial value of content
is normal
, which computes to none
on the ::before
and ::after
pseudo-elements. See the spec.
The reason the initial value of content
isn't an empty string but a value that computes to none
for the ::before
and ::after
pseudo-elements, is twofold:
Having empty inline content at the start and end of every element is rather silly. Remember that the original purpose of the
::before
and::after
pseudo-elements is to insert generated content before and after the main content of an originating element. When there's no content to insert, creating an additional box just to insert nothing is pointless. So thenone
value is there to tell the browser not to bother with creating an additional box.The practice of using empty
::before
and::after
pseudo-elements to create additional boxes for the sole purpose of layout aesthetics is relatively new, and some purists might even go so far as to call it a hack for this reason.Having empty inline content at the start and end of every element means that every (non-replaced) element — including
html
andbody
— would by default generate not one box, but up to three boxes (and more in the case of elements that already generate more than just the principal box, like elements with list styles). How many of the two extra boxes per element will you actually use? That's potentially tripling the cost of layout for very little gain.Realistically, even in this decade, less than 10% of the elements on a page will ever need
::before
and::after
pseudo-elements for layout.
And so these pseudo-elements are made opt-in — because making them opt-out is not only a waste of system resources, but just plain illogical given their original purpose. The performance reason is also why I do not recommend generating pseudo-elements for every element using ::before, ::after
.
But then you might ask: why not have the display
property default to none
on ::before, ::after
? Simple: because the initial value of display
is not none
; it is inline
. Having inline
compute to none
on ::before, ::after
is not an option because then you could never display them inline. Having the initial value of display
be none
on ::before, ::after
is not an option because a property can only have one initial value. (This is why the initial value of content
is always normal
and it is simply defined to compute to none
on ::before, ::after
.)
Using the :after CSS pseudo-element without inserting content
It is possible to use an :after
pseudo-element with the content
property set to the empty string ""
, but not without setting it all (so that it has its initial value none
, which means that the pseudo-element is not generated at all).
The reason why you do not see any effect is that your settings effectively cancel each other out. You set a negative left margin, shifting the element leftwards, but you set an equal amount of padding. The pseudo-element itself is empty and thus invisible, so all that matters is the space that it occupies.
This can be illustrated by drawing an outline. I’m using the value 10px instead of 1px for clarity:
.nav-primary li.level0 a:after {
content: "";
padding-right: 10px;
margin-left: -10px;
outline: solid red;
}
<div class=nav-primary>
<ul>
<li class=level0><a href=foo>bar</a>xxx
<li><a href=foo>bar</a>xxx
</ul>
</div>
How to use :empty pseudo-class and content property together?
Turns out I answered my own question in the asking:
http://jsfiddle.net/M6xZj/2/
You can use :after
with the :empty
element to add something after the UL. It is empty, after all, so it's guaranteed to be located where the list was.
Div with CSS content, after pseudo element is not visible
The content
property replaces all content within the element. By adding content
to a non-pseudo selector, that content will replace the ::before
and ::after
pseudo selector.
So try doing this using the content
property within the ::before
and ::after
pseudo selectors only.
.demo:before {
content: url('http://placehold.it/350x150')
}
.demo:after {
content: 'some text';
display: block;
}
<div class="demo"></div>
css :before and :after pseudo-elements content property
The initial value of content
is none
. When you don't define content
, that value is used, and when that value is used, the pseudo-element is simply not generated at all. An empty string ""
is not the same as none
; the empty string means "insert an empty object", whereas none
means "don't insert anything at all".
Indeed, saying "objects inserted" is basically the same as "pseudo-elements created" or "boxes rendered", etc.
after pseudo element not appearing in code
It's because the pseudo-element isn't generated if the content
value is omitted (since the initial/default value is none
).
Specify a content
value in order to generate the pseudo-element. A value of ''
is sufficient.
.product-show .readMore.less:after {
content: '';
background: rgba(255, 255, 255, 0);
display: block;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 30px;
}
Could i use content attributte in empty pseudo in css?
:empty
is a pseudo-class, which allows you to style an element based on state. It is not possible to use content
attribute with a pseudo class, or at least it does not work that way.
As @HaoWu suggested, you need to use a pseudo-element, like :before
or :after
to provide content to your empty .item
element.
.item:empty:before {
content: 'Content';
}
<div class="item"></div>
How can I distingush between the content property of the ::before element being not specified at all and being specified as an empty string?
Simply add an if truthy clause to test that it has some value.
E.G:
var before = window.getComputedStyle(elem, ':before').getPropertyValue('content');
if(before && before!=="none"){//<-- (IE / FF fix) check it doesn't equal 'none'
//content: is defined but it could still be an empty string
alert("Before="+before);
} else {
//there is no :before content: defined at all
}
Here's the demo. Try changing the css :before
content to test it.
Also, you can reduce the code still further by using getComputedStyle(elem, ':before').content
instead of window.getComputedStyle(elem, ':before').getPropertyValue('content')
.
Related Topics
Affecting Parent Element of :Focus'D Element (Pure CSS+HTML Preferred)
Select the Preceding Sibling of an Element in CSS Using Selectors
How to Add Space Between Elements So They Fill Their Container Div
Ie11 Border Radius and Border Bug
Applying CSS File to Javafx Webview
How to Make Bootstrap Responsive Design Work with Dotnetnuke
Safari and Ie Can't Read Ttf and Eot Fonts
Alternative for Nth-Child for Older Ie Browsers
Why Doesn't Height: 0 Hide My Padded <Div>, Even with Box-Sizing: Border-Box
Vertically Align Bootstrap Badge Inside Heading
Position One Element Relative to Another in CSS
CSS Flexbox Vertically/Horizontally Center Image Without Explicitely Defining Parent Height
How to Create Zebra Stripes on HTML Table Without Using JavaScript and Even/Odd Classes Generation
How to Colorize a White Png Image with CSS Only
CSS 62.5% Why Do Developers Use It
Multiple Classes in CSS Selector
CSS - Parent's Position Is Absolute and Child's Position Is Relative and Vice Versa