DEV Community

Cover image for Code block $ prefix
Glenn Carremans
Glenn Carremans

Posted on

Code block $ prefix

I use the DigitalOcean community tutorials a lot for examples how to setup up different things in Linux (Nginx, MySQL, firewall, ...) and would also advice everyone to use them.

About 3 weeks ago I actually noticed something about their code blocks, some of them (containing terminal commands) started with $, nothing strange about that right?
Well actually it is because you can't copy it, it will only copy the code after the $ prefix. An example of this can be found here.

This caught my interest, I have never noticed this before and couldn't find any good examples how this was done. So I digged through the page source code and found the magical source code for this little piece of art.

It is actually a combination of some good old HTML combined with a little CSS magic. I will try to explain the different parts and at the end show a working JSFiddle example.

The HTML part is actually pretty simple. It is the normal code block syntax with an unordered list in it. This example shows a code block with multiple lines but of course if you only want a one-line code block you can do the same with only one list item (<li>).

        <ul class="prefixed">
            <li class="line">sudo apt-get update</li>
            <li class="line">sudo apt-get install apache2</li>
            <li class="line">sudo apache2ctl configtest</li>

I will split this part up into smaller sections.

This first part is only used to reduce the spacing between each list item. Nothing special about it.

pre .prefixed {
    white-space: normal;
    margin: 0;

Okay now we are getting to the first important part. list-style-type is used to remove the default list item style:

pre .line {
    list-style-type: none!important;

This last part is used to actually add the $ prefix in front of the code block. The first part is to make sure that a user can't copy it. The margins are used to add a little spacing around the prefix, of course can be adjusted how you like.
The most important part is content: "$";, this adds the prefix that we want to all the lines above.

pre .line::before {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    -o-user-select: none;
    user-select: none;
    content: "$";
    margin-right: 10px;
    margin-left: 5px;

I wanted to add this as a little bonus.
It is also possible to add different prefixes to each line without needing to make a different CSS style for each.
Add the prefix attribute, with any value that you like.

<li class="line" prefix="$">sudo apt-get install apache2</li>

In the last CSS block replace content: "$"; with this. It will get the attribute value and use that as the prefix instead.

content: attr(prefix);

This was my first time giving a coding tutorial so I hope you like it. Any feedback is of course welcome.

Top comments (11)

rpalo profile image
Ryan Palo

This is neat! I didn't realize you could pass things directly from HTML attributes to CSS using the attr() function. That seems like a really semantic way of handling cases like this.


glennmen profile image
Glenn Carremans

It always makes me happy to be able to learn new things to other people😄

amdev83 profile image
Aaron L Marks

I came here to say the same thing! I didn't know that you could pass data around like that. This is awesome!

qm3ster profile image
Mihail Malo

I have to admit I usually run away when CSS is being discussed,
but I thought I know most of it.

Well, content: attr(prefix); blew my mind.

glennmen profile image
Glenn Carremans

Lol I am in the same boat as you on this 😂I am a "CSS newbie".
I also still learn a lot from CSS and it amazes me how much it changed compared to a few years ago. In "the old days" you where forced to use JS for a lot of animations but now you can do almost everything with only CSS.

dennisk profile image
Dennis Keirsgieter

Would it also be possible to say if you don't pass on a prefix in the html it shows default ($) and otherwise use the prefix? Seems a bonus on top the bonus to me!

glennmen profile image
Glenn Carremans

Good question! I did a quick search and actually you can.

attr() has an optional fallback, however this is still an experimental feature.

content: attr(prefix, "$");
dennisk profile image
Dennis Keirsgieter • Edited

And here i am looking at the docs and missing the last part about the fallback.. Thanks for that! Doesn't seem to work in my version of chrome yet tho.

rufio profile image
Andy Hattemer

Nice write up Glenn - For me this brought up a follow-up Q for you that might make for another good post...

If it was possible, do you think people would prefer that single-line terminal commands copied from webpages don’t include the linebreak?

(IE. would it be better that the command doesn't run immediately when posted into your terminal)

If so, how would you do it?

glennmen profile image
Glenn Carremans

Interesting question, this might be a good #discuss topic.
I personally like to copy/paste without a linebreak, so I can always double check the command or edit/add things.

Your question "how would you do it?", do you mean as a dev that made the code block or as a user that copy/pasted the command?

itr13 profile image
Mikael Klages

Seems to work well on mobile too, nice find!