Let's say that by design all elements should look like tiles of a given color and with some shadow; something like this:
.panel {
background-color: #bbffff;
padding: 1em;
box-shadow: 0.5em 0.5em 0.5em 0em rgba(0,0,0,50%);
}
<div class="panel">
Some text
</div>
At this point, thinking about writing modular CSS, I'd be already tempted to pick the box-shadow
declaration and put it in its own ruleset,
.down-right-box-shadow {
box-shadow: 0.5em 0.5em 0.5em 0em rgba(0,0,0,50%);
}
so that I can reuse it by adding class="down-right-box-shadow"
to an HTML tag without bringing in also background-color
and padding
declarations.
Now assume that, for some reason, the CSS uses pseudo-elements to create some effects close to those tiles, something like this:
.panel {
background-color: #bbffff;
padding: 1em;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 0.4em;
}
.down-right-box-shadow {
box-shadow: 0.5em 0.5em 0.5em 0em rgba(0,0,0,50%);
}
.panel::after {
content: "";
width: 1em;
height: 1em;
border-radius: 100%;
margin-top: 0.2em;
background-color: blue;
box-shadow: 0.5em 0.5em 0.5em 0em rgba(0,0,0,50%);
}
<div class="panel down-right-box-shadow">
Some text
</div>
Clearly the intent is that the ::after
pseudo-element has the same shadow as everything else on the page, but since it's a pseudo-element, I can't remove the box-shadow
declaration from within it in favour of adding class="down-right-box-shadow"
in the HTML, because there's no element in the HTML for it.
So I have to rewrite the same declaration for .down-right-box-shadow
at least in these two places.
If tomorrow something in the .down-right-box-shadow
ruleset changes, I'll have to remember applying the same change to the .panel::after
ruleset.
Is there any clean way out of this code replication?
Temani Afif has got a point; using variables:
:root {
--down-right-box-shadow: 0.5em 0.5em 0.5em 0em rgba(0,0,0,50%);
}
.panel {
background-color: #bbffff;
padding: 1em;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 0.4em;
}
.down-right-box-shadow {
box-shadow: var(--down-right-box-shadow);
}
.panel::after {
content: "";
width: 1em;
height: 1em;
border-radius: 100%;
margin-top: 0.2em;
background-color: blue;
box-shadow: var(--down-right-box-shadow);
}
<div class="panel down-right-box-shadow">
Some text
</div>
I may be missing something, but this should work as well:
.down-right-box-shadow,
.panel.down-right-box-shadow::after {
box-shadow: 0.5em 0.5em 0.5em 0em rgba(0,0,0,50%);
}
Of course you'd have to add multiple selectors in case you want other elements that are not .panel
, but it solves the multiple box-shadow
problem
.panel {
background-color: #bbffff;
padding: 1em;
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 0.4em;
}
.down-right-box-shadow,
.panel.down-right-box-shadow::after {
box-shadow: 0.5em 0.5em 0.5em 0em rgba(0,0,0,50%);
}
.panel::after {
content: "";
width: 1em;
height: 1em;
border-radius: 100%;
margin-top: 0.2em;
background-color: blue;
}
<div class="panel down-right-box-shadow">
Some text
</div>