Why Do I Need an Empty 'Content' Property on an ::After Pseudo-Element

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:

  1. 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 the none 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.

  2. Having empty inline content at the start and end of every element means that every (non-replaced) element — including html and body — 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



Leave a reply



Submit