Note: This has been tweaked for greater efficiency and simplicity since it was first published.
Borders and dividers are very similar. They’re comprised of three main properties:
- Size
- Style
- Color
In cases of <hr>
elements, you’re even using border styles in most cases. This could be the same with pseudo-element dividers as well (but not always).
A good thing about border properties is that they support shorthand. Instead of writing:
.card {
border-size: 1px;
border-style: solid;
border-color: var(--black-trans-20);
}
Code language: CSS (css)
You can write:
.card {
border: 1px solid var(--black-trans-20);
}
Code language: CSS (css)
This is great, because it means that this entire string can be assigned to a single variable.
The question is, what do we call this variable and how do we make it flexible while supporting an alternate style?
First, we should probably partialize the styles and separate global styles from specific styles.
:root {
/* Global */
--border-size: 1px;
--border-style: solid;
/* Local */
--border-color-light: var(--white-trans-20);
--border-color-dark: var(--black-trans-20);
}
Code language: CSS (css)
Now, we just need to decide how we’re going to deploy the styles. In my opinion, most sites have one primary border style. So, to keep things simple, let’s call the primary border style with just var(--border)
.
It’s all setup like this:
:root {
/* Global */
--border-size: 1px;
--border-style: solid;
/* Local */
--border-color-light: var(--white-trans-20);
--border-color-dark: var(--black-trans-20);
/* Full Tokens */
--border: var(--border-size) var(--border-style) var(--border-color-dark);
}
Code language: CSS (css)
So, for a white card that needs a border, it might look like this:
.card {
display: flex;
flex-direction: column;
gap: var(--content-gap);
background-color: var(--white);
border: var(--border);
}
Code language: CSS (css)
But, what about variants? What if there’s a dark card that needs a light border?
You can also have border variants waiting for deployment. Let’s go back to the initial setup and take a look:
:root {
/* Global */
--border-size: 1px;
--border-style: solid;
/* Local */
--border-color-light: var(--white-trans-20);
--border-color-dark: var(--black-trans-20);
/* Full Tokens */
--border: var(--border-size) var(--border-style) var(--border-color-dark);
--border-light: var(--border-size) var(--border-style) var(--border-color-light);
--border-warning: var(--border-size) var(--border-style) var(--warning);
--border-danger: var(--border-size) var(--border-style) var(--danger);
--border-success: var(--border-size) var(--border-style) var(--success);
}
Code language: CSS (css)
Now, if you need to deploy a variant, you can simply do this:
.card {
--border: var(--border-light);
display: flex;
flex-direction: column;
gap: var(--content-gap);
background-color: var(--black);
border: var(--border);
}
Code language: CSS (css)
Essentially, the value of the border property is always var(--border)
. This presents your default border style. Then, you can choose to override your default style on a case by case basis with another token when/if needed.
You can do the same thing with divider styles.
5 comments
Isaura
Very neat! The power of locally scoped variables and ACSS shining again 👌
Nicolás Cubero
Great solution! Thanks.
Tim Veach
Absolutely awesome!
Tincher
Love it!!
Dahunsi
Absoeffing Brilliant