CSS content and attr

By  on  

CSS is becoming more and more powerful but in the sense that it allows us to do the little things easily.  There have been larger features added like transitions, animations, and transforms, but one feature that goes under the radar is generated content.  You saw a bit of this with CSS counters, where we used the counter and counters expressions to set the content of a given element.  There's another expression, attr, that allows for CSS-based content creation as well. Let me show you how attr an content can work together!

Basic content Usage

The content property allows the developer to statically or (somewhat) dynamically set the content of a pseudo-element:

.myDiv:after { content: "I am hardcoded text from the *content* property";  }

Remember to make the element (not the pseudo-element) position: relative if you plan to absolutely position the pseudo-element.

content and attr

In the case that you'd like to use an element attribute as content (this being the dynamic usage of content), you may do so with the attr expression:

/* <div data-line="1"></div> */

div[data-line]:after { 
	content: attr(data-line); /* no quotes around attribute name! */
}

attr is typically used with custom data- attributes since traditional element attributes are good for functionality but not so much or text presentation.

content Concatenation

Concatenating strings is done via simple spacing:

/* <div data-line="1"></div> */

div[data-line]:after { 
	content: "[line " attr(data-line) "]"; 
}

Trying to concatenate via JavaScript "+" or any other symbol will bomb ... not that I found that out the hard way or anything...

The ability to use generated content with an attr expression is quite exciting.  You can see this used within PrismJS' line-highlighting plugin and a line-number plugin I'll release soon.  These generated content tactics make pseudo-elements all the more valuable too!

Recent Features

  • By
    How to Create a RetroPie on Raspberry Pi &#8211; Graphical Guide

    Today we get to play amazing games on our super powered game consoles, PCs, VR headsets, and even mobile devices.  While I enjoy playing new games these days, I do long for the retro gaming systems I had when I was a kid: the original Nintendo...

  • By
    Being a Dev Dad

    I get asked loads of questions every day but I'm always surprised that they're rarely questions about code or even tech -- many of the questions I get are more about non-dev stuff like what my office is like, what software I use, and oftentimes...

Incredible Demos

  • By
    Create a Trailing Mouse Cursor Effect Using MooTools

    Remember the old days of DHTML and effects that were an achievement to create but had absolutely no value? Well, a trailing mouse cursor script is sorta like that. And I'm sorta the type of guy that creates effects just because I can.

  • By
    jQuery Comment Preview

    I released a MooTools comment preview script yesterday and got numerous requests for a jQuery version. Ask and you shall receive! I'll use the exact same CSS and HTML as yesterday. The XHTML The CSS The jQuery JavaScript On the keypress and blur events, we validate and...

Discussion

  1. thanks for this! I first saw the attr() expression from this codepen: http://codepen.io/TrentWalton/pen/bImfn

    Is there anyway to get the value of the inner text? like .innerHTML in JS?

    seems silly to write the content ‘gzip’ twice, when all we want to do is duplicate the content inside a given element.

  2. dj

    Nice, concise tip. Don’t forget to give the HTML code, which your CSS is working against, within the body of the article text – for ease of reading and clarity sake.

  3. Good writeup, David! I’d like to point out that content and attr are also good solutions for translated/internationalized content. The translated content can be defined as an element attribute instead of creating/maintaining translated content in stylesheet(s).

  4. Aaron

    What is the browser support for this?

  5. Also, this is very useful if you have to provide a printable page, this way you don’t lose any links and other information that might be useful.

  6. I love the trick, but with what I tried, copy/paste doesn’t work if the text is added with CSS ‘content’. In a lot of contexts, it makes this technique unusable as copy/paste really is an awesome feature!

  7. Cameron Bright

    very very USEFUL ! solved my problem, I first tried to use multiple pseudo elements but this is better,

  8. César Pacha

    Is it possible to use this pseudo selector with an image and display a content with it’s url? something like this

    .galImg:after{
    content:attr(src);

    }

  9. span:before{
    content: attr(data-text);
    }
    

    I want to replace “data-text”s content by css. data-text placed in php. so if i chenge ‘content: ‘my text’; is not working. How can i change it?

    • What’s the issue exactly? If you want the content from a data-text attribute to appear, just leave it data-text. Otherwise, just change what attribute it should be referring to.

  10. @César Pacha: In theory yes, though doesn’t seem to support use of the :before and :after pseudo selectors:

    http://codepen.io/anon/pen/GgPdXN

  11. Samuel Willems

    @Edward it does! However img doesn’t suport pseudo elements c;

  12. Wow, I half-heartedly Googled this issue thinking it probably doesn’t exist, but it totally does! Thank you so much for making me aware.

  13. Just looking at the CSS Values and Units Module Level 3 editors draft. attr() is planned to work for all properties rather than just content.

    This opens up incredible possibilities for frameworks like bootstrap in the future (when browser support catches up).

    c[sm] {
    	/* Width = (100% / TotalColumns) * ColumnSmall */
    	width: calc( calc( 100% / attr(tc integer, 12) ) * attr(sm integer, 0) );
    }
    
    
    	Column with default total columns of 12
    
    
    	Column with total columns set to 10 causing sm=5 to set the width to 50%.
    
    
    	Completing with a second column at 50%.
    
    

    This functionality brings a whole new layer to the CSS game. I’m very excited to see this implemented.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!