Register to get access to free programming courses with interactive exercises

Pseudo-elements Content layout fundamentals

In previous lessons, we dealt with pseudo-classes, which involve changing existing elements depending on their state. Is it possible to specify or create styles for elements that aren't in HTML? Yes! CSS has a concept called pseudo-elements for just such a purpose.

Let's look at styling a drop cap as an example. Drop caps, or dropped capitals, refer to the first character in a paragraph when it's enlarged. You can often find this technique in fairy tale books or olde worlde books. What's the best way to do this? The first thing that comes to mind is to wrap the first character in a separate tag and style it.

<article>
  <p>
    <span class="first-letter">T</span>here once was an old man and an old woman <br>
    By the blue sea; <br>
    They lived in a ramshackle dugout <br>
    For exactly three and thirty years.
  </p>
</article>
article {
  color: #37474f;
  font: 25px/1.5 serif;
}

.first-letter {
  color: #f44336;
  font-size: 2em;
  line-height: 1;
}

A good and working option, suitable for small changes in some texts. What problems could be hidden here? Firstly, if there are a lot of these texts, then it takes a long time to add tags to each desired paragraph, thus increasing the risk of error. You might forget to put a tag or not put a tag on the first letter as you should. Secondly, it becomes less scalable. When it comes to getting rid of drop caps, you need to remove all the classes or remove the styles, but then there'll be unnecessary tags left over, which is more likely to confuse you.

How can you get out of this situation? This is where pseudo-elements come in. They can virtually create the tag we need and style it only using CSS. This solves the two problems described above:

  1. There's no need to put in new tags. All you have to do is specify the desired selector in CSS
  2. When you remove a class like this, there'll be no unnecessary HTML tags left over

The ::first-letter pseudo-element is responsible for styling the first character. It'll wrap the first character virtually and apply custom styles to it. Let's rewrite the example a bit and give drop caps to all the paragraphs within the article.

article {
  color: #37474f;
  font: 25px/1.5 serif;
}

article p::first-letter {
  color: #f44336;
  font-size: 2em;
  line-height: 1;
}

The result is the same, but in terms of browser performance, there'll have been lots of changes. The browser automatically found the first character in the paragraph, which is within the article. It wrapped it and applied the styles described in the CSS.


Interestingly, pseudo-elements, in terms of syntax, are very similar to pseudo-classes, but two colons are used instead of one :. Browsers will correctly handle a pseudo-element such as :first-letter. It's not immediately obvious which is a pseudo-class and which is a pseudo-element, so always use :: to specify a pseudo-element.


before and after

You could write an entire course about these two pseudo-elements. Their interaction with websites cannot be overstated. Used in most cases, ::before and ::after are by far the most important pseudo-elements. You can think up all sorts of different ways to use and style them as you learn about layout design.

In the lesson about lists, we said that styling markers are most often done with pseudo-elements. In this part, we'll look at how to do it.


Note: there'll be properties here linked with the positioning of elements. All of these properties will be studied in the CSS: Positioning course. If you don't understand some parts of CSS, don't worry. You'll soon learn how all the new properties work.


::before and ::after allow you to create new content inside the HTML tree. This content is linked to a certain element and can appear before or after it. That's why pseudo-elements are called that:

  • ::before is a pseudo-element that allows you to add content before the selected element
  • ::after is a pseudo-element that allows you to add content after the selected element

Each of these pseudo-elements must include a special content property, which specifies what should be inside. Without this property, the ::before and ::after pseudo-elements won't work!

Let's create a block-level element and use the new pseudo-elements.

<div class="square bg-black text-white">
  <p>The content inside the block</p>
</div>
.square::before {
  content: "Text before the content inside a block";
}

.square::after {
  content: "Text after the content inside the block";
}

All content inside the ::before and ::after pseudo-elements is inline. In other words, it has the display: inline property by default. You can easily change this and work with pseudo-elements as if they were normal elements inside an HTML document.

This opens up truly limitless possibilities for styling elements with CSS. Many techniques are built on the use of pseudo-elements. Create custom list markers using an image.

<h1>Learning on Hexlet</h1>
<ul class="hexlet-ul">
  <li>A great deal of theory</li>
  <li>Plenty of practice and additional assignments</li>
  <li>Comprehensive projects to consolidate knowledge</li>
</ul>
.hexlet-ul {
  list-style: none;
}

.hexlet-ul li {
  position: relative;

  margin-bottom: 20px;
}

.hexlet-ul li::before {
  position: absolute;
  left: -30px;

  width: 20px;
  height: 20px;

  background-image: url(https://assets.codepen.io/1425525/hexlet_logo.png);
  background-repeat: no-repeat;
  background-size: cover;

  content: '';
}

Let's look at what happens in the .hexlet-ul li::before pseudo-element:

.hexlet-ul li::before {
  width: 20px;
  height: 20px;

  content: '';
}

This part of the CSS code specifies empty content. Since we only want to add an image, we don't need any symbols. This field can be left blank, but you must add it. Certain height and width frames are set for the element. It's in these frames that we'll put the image.

.hexlet-ul li::before {
  background-image: url(https://assets.codepen.io/1425525/hexlet_logo.png);
  background-repeat: no-repeat;
  background-size: cover;
}

Now set an image for the block. To do this, we use three properties:

  1. background-image is a property that allows you to set an image as a background. Inside, we use the url function to specify the address where the image is located
  2. background-repeat - repeat the image. If we can repeat the image, does it mean that we have to? Not in this case, because we need a specific image, not a repeating background. The value no-repeat prevents the image from being repeated
  3. background-size manages the image size. The cover keyword scales the image to maintain its proportions and fits it into the height or width of an existing block

By positioning this pseudo-element, we can now use the image as a list marker. It didn't have to adjust the image, because that job was left to CSS.


Do it yourself

Repeat all the examples given in the lesson. Try different property values. For the list, use the ::after element, which adds a small image after the list item


Recommended materials

  1. Documentation on background CSS property
  2. W3C spec on pseudo-elements

Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time
profession
Layout with the latest CSS standards
5 months
from scratch
under development
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.