Today let's work with CSS pseudo-selectors like :first-letter
, :last-of-type
& :after
to build nice little typpgraphic elements in four different color themese that will spice up your text.
Read the full article or watch me code this on Youtube (TL;DW Speedrun):
Result
First Things First - Colors
To have all the colors at hand, each one is defined as a CSS custom property (aka variable) inside the :root
scope. For a slight taste of theming the variables background-color
and foreground-color
are defined and used later on.
:root {
--cc-p-1: #d4aee0;
--cc-p-2: #8975b4;
--cc-p-3: #64518a;
--cc-p-4: #565190;
--cc-b-1: #44abac;
--cc-b-2: #2ca7d8;
--cc-b-3: #1482ce;
--cc-b-4: #05597c;
--cc-g-1: #b2dd57;
--cc-g-2: #57c443;
--cc-g-3: #05b853;
--cc-g-4: #19962e;
--cc-y-1: #fdc82e;
--cc-y-2: #fd9c2e;
--cc-y-3: #d5385a;
--cc-y-4: #911750;
--cc-s-1: #d9d9d9;
--cc-s-2: #9e9e9e;
--cc-s-3: #666666;
--cc-s-4: #2b2b2b;
--foreground-color: white;
--background-color: var(--cc-s-4);
}
Color Themes
There will be four different color themes for the typographic elements: Amethyst (purple), sapphire (blue), emerald (green) and amber (yellow/orange/red). To make these themes easily usable, a <section>
element must have one of the four classes given below, whereas each class simply defines a set of CSS variables which are later used for the gradients.
section {
&.amethyst {
--c-1: var(--cc-p-1);
--c-2: var(--cc-p-2);
--c-3: var(--cc-p-3);
--c-4: var(--cc-p-4);
}
&.sapphire {
--c-1: var(--cc-b-1);
--c-2: var(--cc-b-2);
--c-3: var(--cc-b-3);
--c-4: var(--cc-b-4);
}
&.emerald {
--c-1: var(--cc-g-1);
--c-2: var(--cc-g-2);
--c-3: var(--cc-g-3);
--c-4: var(--cc-g-4);
}
&.amber {
--c-1: var(--cc-y-1);
--c-2: var(--cc-y-2);
--c-3: var(--cc-y-3);
--c-4: var(--cc-y-4);
}
}
Basic Principle
CSS allows us to specify multiple linear-gradients
which are then nicely blended into each other. Luckily also background-size
& background-position
accept multiple, comma separated values, so each gradient can be sized and positioned inidividually. However, this time we're not intersted in creating actual gradients, but tiny mosaic squares each having a unique, so the gradients are created with two times the same color. So in order to create a background containing four squares, the background
property is setup to have four linear gradients with two times the same color. Also note that setting background-origin
to border-box
is essential for this to work.
<selector> {
background:
linear-gradient(
var(--c-1),
var(--c-1)
),
linear-gradient(
var(--c-2),
var(--c-2)
),
linear-gradient(
var(--c-3),
var(--c-3)
),
linear-gradient(
var(--c-4),
var(--c-4)
);
background-origin: border-box;
background-repeat: no-repeat;
}
Now each gradient is positioned in the top left, top right, bottom left and bottom right corner which is achived by providing four x/y pairs tothe background-position
property:
<selector> {
...
background-position:
0% 0%,
100% 0%,
0% 100%,
100% 100%;
background-size: 50% 50%;
}
SASS Mixins for Reusability
Since we'll be using the gradient setup from above multiple times, we'll group it into two mixins for easy reusing:
@mixin mosaic-base() {
background:
linear-gradient(
var(--c-1),
var(--c-1)
),
linear-gradient(
var(--c-2),
var(--c-2)
),
linear-gradient(
var(--c-3),
var(--c-3)
),
linear-gradient(
var(--c-4),
var(--c-4)
);
background-origin: border-box;
background-repeat: no-repeat;
}
@mixin mosaic() {
@include mosaic-base;
background-position:
0% 0%,
100% 0%,
0% 100%,
100% 100%;
background-size: 50% 50%;
}
Headline
The headline is going to have a bar below itself having four partial lines positioned one after another:
<section>
<h2>Mosaic Typographic Elements</h2>
</section>
The mosaic gradients are simply applied to an ::after
pseudo-class so there is no additional markup needed. Since the h2
styles are nested within the section
selector, the variables for the color theme defined there can be used perfectly well.
section {
h2 {
display: block;
font-weight: 300;
text-align: center;
font-size: 2rem;
position: relative;
&::after {
--width: 8rem;
--height: 2px;
content: "";
display: inline-block;
width: var(--width);
height: var(--height);
position: absolute;
left: 50%;
bottom: -1rem;
transform: translate(-50%, -50%);
@include mosaic-base;
background-position:
0% 0%,
33% 0%,
67% 0%,
100% 0%;
background-size:
25% 100%,
26% 100%,
25% 100%,
25% 100%;
}
}
}
First Letter Styling
In order to style each first letter that appears after a heading let's use the so called adjacent sibling selector to identity each paragraph of text <p>
coming directly after a heading <h2>
. The :first-letter
pseudo-class allows us to apply styles very selectively to - as the name strongly indicates - the very first letter of the paragraph. In order to have text flowing nicely around the letter setting float: right;
is necessary. The rest is simply adjusting font size and spacings to make it look nice.
section {
h2 + p:first-letter {
font-weight: 900;
font-size: 1.6em;
float: left;
margin-right: 0.1em;
margin-top: 0.2em;
padding: 0em 0.1em;
color:
var(--background-color);
@include mosaic;
}
}
Ruler Styling
The HTML <hr>
element alows us to put a horizontal ruler for dividing e.g. paragraphs or any other elements from each other.
<hr>
So, here we'll be overriding the styling of the <hr>
element to have a mosaic in its center tilted by 45 degrees. Again, we're using the ::after
pseudo-class to create the necessary element for the mosaic without requiring additional markup.
section {
hr {
--size: 1rem;
width: 60%;
height: 1px;
border: none;
background: var(--cc-s-2);
&::after {
content: '';
display: inline-block;
width: var(--size);
height: var(--size);
position: absolute;
left: 50%;
transform:
translate(-50%, -50%)
rotate(45deg);
border: 4px solid var(--background-color);
@include mosaic;
}
}
}
Tombstone (you read that right)
A so called tombstone appears at the end of e.g. an article letting the reader know, that the end was reached. The :last-of-type
pseudo-class helps us to identify the last element of a given type, so e.g. the last paragraph of text in a section, which is exactly what we need. Now, all we have to do is to simply add another ::after
pseudo-class containing the mosaic gradients and being floated to the right. And done! 😎
section {
p:last-of-type::after {
--size: 0.5em;
content: '';
float: right;
width: var(--size);
height: var(--size);
position: relative;
top: 0.5em;
@include mosaic;
}
}
Top comments (3)
Hello CrayonCode, I am delighted with your article, I would like to talk about programming, are you willing?
Hello Emanuel,
What's your main field of interest (web, datastructures, coding practices,...)? What kind of discussion/talk do you have in mind?
Web programming