How to add multiple values in a single CSS property

Adir SL
UX Collective
Published in
12 min readApr 6, 2020

--

How to Add Multiple Values in a Single CSS Property
How to Add Multiple Values in a Single CSS Property

Last year I started teaching basic Front-End Development courses (HTML/CSS) in a few Design Schools, I also gave a talk in a few meetups to an audience of more seasoned JavaScript developers.

These experiences were awesome and it was really fun to see the differences between JavaScript developers and Designers taking their first steps in the world of HTML and CSS.

One of the things these both groups had trouble with was the notion of typing multiple values into one CSS property, so that’s what we’ll learn in this article.

Why Use Multiple Values in CSS

Every CSS rule consists of at least 3 parts: Selector, property and value(s), as you can see in the image below.

Basic CSS Rule Structure Example, NOT a Real Rule
Basic CSS Rule Structure Example, NOT a Real Rule

The values are the red stuff, they’re the content of this property, think of a property like border, the whole point is the value, how thick should this border be? what color? what style?

It would be great if we could fit all that border content into one property, well we can and we can even fit much more than that.

Borders, Paddings and Margins

As I already mentioned border, we’ll start with this one, you probably know that borders in CSS can be defined by trait, like those in the example code below.

div{
border-width: 10px;
border-style: solid;
border-color: blue;
}
CSS simple border property
CSS simple border property

However, it can get much more complicated than that if you need different borders to different facets of your element, you can add top, left, right, bottom as I did in this code example, but I gave up after two facets.

div{
border-top-width: 10px;
border-top-style: solid;
border-top-color: blue;
border-left-width: 2px;
border-left-style: solid;
border-left-color: red;
}
Two different borders, one on the left and one on top
Two different borders, one on the left and one on top

We can definitely make this code shorter.

We can definitely make this code shorter by just implementing our agenda of multiple values per property and make all the sides appear in the border properties from our first example.

div{
border-width: 10px 2px 5px 8px;
border-style: solid dashed dotted solid;
border-color: blue red purple green;
}
Four different borders, one for each facet
Four different borders, one for each facet

Notice that in the above example the order of the values are: top, right, bottom, left. No commas needed for borders at this time.

If you don’t need the different sides, you can also just type your border in one line as in the example below, no separate border-style or border-color property needed.

div{
border: 10px solid blue;
}

Of course, if we only need the change of color between borders you can have one property for the border property and another just changing what needs to be changed, use the cascading nature of CSS in your favor.

div{
border: 10px solid blue;
border-color: blue red green purple;
}
Four different borders with more elegant code
Four different borders with more elegant code

We can also just have 2 values in our code, the first value will indicate our top and bottom border, the second value will indicate our sides borders, both left and right.

div{
border: 10px solid blue;
border-color: blue red;
}
Two different borders, this time facing each other
Two different borders, this time facing each other

If we have one value it will indicate all four sides, if we have 2 values it will treat them as vertical and horizontal values

Everything we saw with borders can also be applied to margin and padding, if we have one value it will indicate all four sides, if we have 2 values it will treat them as vertical and horizontal values, that’s very useful for buttons padding for example.

If we type 4 values, it will treat them as the four sides of our element, in this order: top, right, bottom, left. Just as we saw in the border property.

.div1{
padding: 10px; /*same all around*/
}
.div2{
padding: 10px 60px; /*vertical and horizontal*/
}
.div3{
padding: 10px 100px 60px 200px; /*top,right,bottom,left*/
}
CSS padding shorthand with one value, 2 values and 4 values
CSS padding shorthand with one value, 2 values and 4 values

Border-radius works very much in the same way, we can type in one value and all our corners will curve the same way, if we’ll type 2 values then the first value will affect the top-left and bottom-right corners and the second value will affect the remaining two corners.

Just like the border property itself, if we’ll type in 4 values we’ll see the corners get affected in the following order: top-left, top-right, bottom-right, bottom-left.

.div1{
border-radius: 20px; /*all corners will curve by 20px*/
}
.div2{
border-radius: 20px 100px; /*a leaf effect*/
}
.div3{
border-radius: 10px 30px 50px 100px; /*every corner is unique*/
}
Border-radius with one value, 2 values and 4 values
Border-radius with one value, 2 values and 4 values

However border-radius can get even more values to create more complex shapes like an egg, see the example below.

div{
border-radius: 40% 60% 25% 75% / 35% 75% 25% 60%; /*egg*/
}
CSS egg shape achieved with border-radius
CSS egg shape achieved with border-radius

In those 8 values border-radius, the first 4 values are just like before, top-left, top-right, bottom-right, bottom-left. The last 4 values (separated by a “/”) are the same corners in the same order, only now the radius isn’t by “x” amount but it’s from point to point.

This way we can create more kinds of shapes since any corner can be manipulated and scaled, not only proportionally, to fit our needs, we gain full control of the curves, not just a simple numeric indicator.

Box-Shadows and Filters

Everything we saw up until now was just a shorthand, a shortcut for us to write the same rules with less amount of code, but not all multiple values are just shorthand.

Some properties cannot be used in any other way, this makes this trick of adding multiple values not only clever but necessary, otherwise you’ll end up giving up on good ideas or worse, tweaking your HTML and adding unnecessary elements to compensate on your CSS.

For the sake of clarity I kept all the values in this order: offset-x, offset-y, blur amount, offset-size, color.

Box-shadows are typed here with 5 values, some of them can be omitted since it’s zero but for the sake of clarity I kept all the values in this order: offset-x, offset-y, blur amount, offset-size, color.

One of the most interesting properties is box-shadow, we can’t add multiple box-shadows because they’ll end up rewrite each other during the cascade (the “C” in CSS, remember?)

div {
box-shadow: 12px 12px 0 0 red;
box-shadow: 8px 8px 0 0 green;
}
CSS box-shadows overwrite each other
CSS box-shadows overwrite each other

The shadows should be separated by a comma.

In the example above the div will end up with the green box-shadow with no red shadow to be found, but we can use our “trick” of typing multiple values in the same property and none of them will get overwritten, the shadows should be separated by a comma.

div {
box-shadow: 8px 8px 0 0 green, 12px 12px 0 0 red;
}
Multiple CSS box-shadows
Multiple CSS box-shadows

The example above will leave us with both shadows, the green with 8px and the red below it with 12px, so we’ll only see it popup in the remaining 4px but we can tweak the blur or the opacity to make sure it’s there, and it is.

The shadows are typed in the opposite order of which we render them.

Notice that the shadows are typed in the opposite order of which we render them, the red gets rendered first and then the green is rendered on top of it, if we flip the order of the shadows, we’ll only see the red one as it will be on top of the smaller green shadow, blocking our view.

If we want our shadows to be inside our element (inner-shadow, as it’s called in most graphic software), we can use the inset parameter, notice that even though our axis is now flipped, and we’ll need to use negative values to target the same shadow position as before, our typing order stays the same, we don’t need to modify it at all.

div {
box-shadow: -8px -8px green inset, -12px -12px red inset;
}
Multiple CSS box-shadows with the inset value
Multiple CSS box-shadows with the inset value

Everything said here about box-shadow is also true for text-shadow, they’re rendered in the same way and they can be layered in the same way, just remember the commas and the backwards rendering order.

CSS also offers us another way of rendering shadows on elements, we can use the filter property as another kind of shadow, drop-shadow as seen in the example below.

div {
filter: drop-shadow(8px 8px 0 green) drop-shadow(8px 8px 0 red);
}
Two drop-shadow filters
Two drop-shadow filters

Just like the box-shadow, if we type these shadows in different filter properties, our property will get overwritten, but this time we don’t need the comma, as these values are already contained within their own brackets.

These shadows will render in the expected order, as the green shadow will appear first and then the red one, notice that with drop-shadow these will add up on top of each other instead of blocking each other as we saw with box-shadow.

Notice that with drop-shadow these will add up on top of each other instead of blocking each other as we saw with box-shadow.

The filter property is much more than drop-shadow, we can use any value of this property to layer our filters on top of each other.

.div1{
/*this will render a green shadow:*/
filter: hue-rotate(180deg) drop-shadow(8px 8px 0 green);
}
.div2{
/*this will render a purple shadow:*/
filter: drop-shadow(8px 8px 0 green) hue-rotate(180deg);
}
Same filters with a different rendering order, remember that the original div color is still hot pink
Same filters with a different rendering order, remember that the original div color is still hot pink

The order of the values will determine how they’re rendered, first typed is the first to be rendered, this way you can layer any filter you want: blur, grayscale, contrast, the sky is the limit.

Transforms and Transitions

In my lectures I frequently hear students hitting themselves for “wasting” transform on translate or scale and than they find out they need also to rotate the element and they’re stuck.

Good News! You can layer multiple transform values, and yes, you can do it in one CSS property as well.

Transform works a lot like box-shadow as it renders backwards, but it also looks like filter as it doesn’t need commas between values as those are contained in their own brackets.

div1:hover {
/*this will render the ROTATE first*/
transform: translate(0, 100px) rotate(45deg);
}
.div2:hover {
/*this will render the TRANSLATE first*/
transform: rotate(45deg) translate(0, 100px);
}
Same transforms with different rendering orders
Same transforms with different rendering orders

Transform works a lot like box-shadow as it renders backwards.

Notice that I specifically used translate with two values and not translateY to show that inside the brackets the syntax didn’t change and all of the regular transform rules still apply.

Between the two translate values you still need the comma, this means you don’t need a comma between the transform values themselves, in this case, the translate and rotate values.

Transform-origin can also get more than one value, it can get one per axis, so two in 2d elements, these values can be defined as pixels, percents etc. These values can also be set with keywords like “center”, “top”, left”. By the way, those keywords cannot be added to a z-axis in a 3d element.

When typing just one value it will indicate both axis, unless this value doesn’t exist on the other axis, like “left” or “top” for obvious reasons. When typing two values the first one will indicate the x axis and the second the y axis, unless those keywords are reserved for a certain axis, in that case there’s no difference between typing “top left” and “left top”.

div{
transform-origin: center center; /*x:50%, y:50%*/
transform-origin: right bottom; /*right+bottom*/
transform-origin: 50% 10%; /*x:50%, y:10%*/
transform-origin: 10%; /*10% on both axis*/
}

CSS transition is probably the most fun example of this, as we can’t get more than one transition at a time unless we use multiple values, and any one transition by itself can also be typed in shorthand values, so it might look confusing at first.

Let’s start with the more simple shorthand typing of this transition property, you can see in the example below we have our transition in 4 different properties.

div{
transition-property: background-color;
transition-duration: 300ms;
transition-timing-function: linear;
transition-delay: 0s;
}

Of course we can shorten it into only one property called simply transition, similar to what we did with the border property.

div{
transition: background-color 300ms linear 0s;
}
Simple example of CSS transition on hover
Simple example of CSS transition on hover

This will produce the exact same transition effect on the div element, only with less code typed, but what if we want more than just one transition?

We can type as many as we want giving we separate them with a comma, just like we saw earlier with box-shadow. Keep in mind that every transition will have its own duration, timing-function and delay.

div{
transition: background-color 300ms linear 0s, transform 500ms ease-in-out 300ms;
}
Two transition firing one after the other due to the transition delay
Two transition firing one after the other due to the transition delay

The example above shows a div with 2 transitions, once the background-color is done, the transform starts because of its transition delay, of course we can make them work simultaneously by removing that delay, like in the example code below.

div{
transition: background-color 300ms linear 0s, transform 300ms ease-in-out 0s;
}
Two transitions working together simultaneously, without any delay
Two transitions working together simultaneously, without any delay

We can also use our transition with “all” instead of the specific property we need to change. It’s a great way to type fast for testing purposes and not to have to stop typing and count your transitions, it is really liberating sometimes.

div{
/*transition every property change:*/
transition: all 300ms linear 0s;
}

There are problems with an “alltransition, it’s not meant for production-ready code.

There are problems with an “alltransition, it’s not meant for production-ready code, and here are those problems:

  1. Performance: this “all” transition is telling the browser to expect a change in every CSS property. Every single rule we type (and the browser defaults) are now checking if something has changed or not, and most of them will not change so it’s really a waste of resources.
  2. Artistic: once you use “all” in your transition, you can’t separate them to different timing-functions and different durations (and delays, of course) so I can almost guarantee your transitions will look worse than it could.
  3. Teamwork: when we use “all” on an element every property that changes will display an animation between those states, even properties we don’t need them to, even properties we (or our team) change in JavaScript later on, are we sure that won’t happen in this project? even a year from now when the team might refresh it.

what I usually end up doing is just typing “all” while I’m typing fast and productively, when the transition is done I replace it with the properties I actually change to separate them and giving the animation more detail with different durations, delays and timing-functions.

What I usually end up doing is just typing “all” while I’m typing fast and productively, when the transition is done I replace it with the properties I actually change.

Summary

We saw how we can type multiple values into a single CSS property, some of them were shorthand in the name of productivity and some were really the only way to make it happen.

Multiple box-shadows and transitions are especially useful, in my opinion, as they really are open-ended and you’re only limited by your own imagination. Some people use multiple box-shadows to enable a completely new design trend like neumorphism, for example.

Neumorphism, the current design trend
Neumorphism, the current design trend

There are a lot more examples of multiple values in CSS and I couldn’t cover all of them. If you’re interested in learning more I advise you to start with the background property as it’s grown to cover gradients, which is also quite open ended and fascinating.

I hope you enjoyed reading this article, I’ll appreciate claps and sharing on social media, you can find me at Twitter, let me know what you thought of it.

You also might enjoy to check out my codePen page and you’re welcome to follow me on my quite new Dribbble acount.

--

--