Check out a free preview of the full Dynamic CSS with Custom Properties (aka CSS Variables) course

The "Strings & Numbers in Strings" Lesson is part of the full, Dynamic CSS with Custom Properties (aka CSS Variables) course featured in this preview video. Here's what you'd learn in this lesson:

Lea discusses some of the caveats with strings in relation to custom properties, how to display a number through the generated content, and how to convert numbers to integers. Only integers can be converted to strings via counter-reset which in turn will allow them to be accepted by content.


Transcript from the "Strings & Numbers in Strings" Lesson

>> So far we've discussed colors, we've seen numbers and lengths and angles. But we haven't discussed anything about strings in relation to custom properties. And there are some caveats there. So let's take a look at this example, where we're using an emoji custom property, to specify an emoji that we want to add, before and after our heading text.

So we use it like this, and in our CSS, we've placed content var emoji. And we also want to transform the emoji on the after pseudo element, so that we flip it. However it's not working, no emoji is showing up. Can you see what the problem is? It's missing quotes.

Once we add the code that works just fine and we need to specify a different display mode here to actually be able to apply transforms and that's about it. It wraps right now but, that's what it was. So if your custom property contains a string don't forget the quotes.

This seems like the most elementary thing ever, but you would be, amazed at how many times people forget the quotes. So this is the viewport demo that we've seen previously, and let's fix it so that it works again. Remember, we were trying some experiments. All right, this works now.

And what we wanted to do here is we wanted to actually output the value of p so that instead of saying your viewport it says 50% of your viewport. So let's try to do that, we're gonna use the before Pseudo element, and we're gonna use this and then concatenate it.

Actually, let's try a static value first. So if we hard code the 50%, it works fine. And even if the 50 is in a different, Is in a different string, cuz the content property accepts a series of strings. But when we try to replace this with our custom property, it fails, the entire thing disappears, the entire content property, nothing shows up.

And what is the problem here?
>> In quotes?
>> Yep what we've done here is basically equivalent to doing this which doesn't work. And again the number of times I've seen people try to output numbers through the content property. In JavaScript that works, you can concatenate strings with numbers and it works in CSS it doesn't work.

So how can we actually output this number is it possible at all? It is but we have to use something that is a bit of a hack so remember counter? There is a property called counter reset that allows us to set a counter, let's call it p to a number let's say 40 here.

We're gonna hard code it first to make sure everything works. And now, whatever we put here, we can actually output through the content property. So we can just put our variable here and now it works and we can change this, And it works just fine. It's a bit of a hack to use counters for this, but right now, it's the only way we have.

There are a lot of discussions in the CSS working group about adding ways to convert between different data types, but right now none of these have been Spector implemented. So content only accepts strings, it doesn't actually do any typecasting, but you can't convert numbers to strings through counter reset.

So the previous example was a little bit of contrived but there are actually useful applications of this. So here we have our familiar bar chart, and we are using the content property to output 5% on every bar. We're also putting the letters just for debugging, but I can remove those.

And, what we want to do here is we want to output the actual percentage of each bar. So let's look at the values of this p property, their percentages and as you might guess, Doing this doesn't work. However, If we try to do the counter trick, That also doesn't work.

Unfortunately, it's the same problem as what we faced earlier with length that we wanted to convert to numbers. And, Even though it's ideal to be able to expose a nice API and hide all the ugliness in places where it can't be seen, in this case, we need to actually change our styling API.

And we need to make these p variables accept numbers not percentages, because with numbers, we can do anything, we can convert them to anything. But with percentages, we can only have percentages. So let's do that, well, I'm gonna go through here, replace all these with numbers, and obviously we'll need to modify our code that sets the height to convert the numbers to percentages.

And notice that now, this already works, it's already outputting the percentage that I have, I only need to concatenate it with an actual percentage sign. Do you see any problems here?
>> Except for that second the last bar.
>> Yeah, and why do you think that is?
>> Floats?

>> Exactly, so let's look at the documentation for counter reset. If we look at the syntax, the syntax is actually integer, not number. Counter reset becomes invalid if we try to use a number there. So then we just get a counter that is, whatever it would have been if we hadn't used counter reset at all, so 0.

So unfortunately, this counter trick only works with integers. And I suppose at this point we could throw our hands up in the air and say, only use this if you have integers. What if we could convert the number we have to an integer? Could we do that? So there is a way to do it, It's a little bit roundabout, but we can register a property.

We could call it integer and to make it reusable, whose syntax is integer. And let's make its initial value be 0 oops, and inherits would be, I guess through and then, If we set this integer to p, And not just p but also p in a calculation. Let's say plus 0, and then we use this integer here, that actually works.

And I think we can even skip the plus0, yeah, as long as it's inside the calc it works. It just converts whatever we have here to an integer because we're setting a custom property that's registered as an integer. Obviously, this will only work if a property is supported, if that property is not supported, the rest would work, we would just get zero for that bar.

This trick was invented by Anna Tudor, and she even had formulas to control how this rounding happens. By default, the browser just rounds in this case, you could also add point five or subtract point five to make it floor or seal depending on what you want. So you can convert the number to an integer by assigning it to a property that is registered as an integer inside calc.

And this is how you could control how the rounding happens and yes, this is a hack but as we know sometimes we have to use hacks. And as long as hacks are encapsulated inside code that does not need to be changed by others using our component styling our component.

It can sometimes be acceptable, make sure to document it well so that other developers know what you're doing if they're reading your code. It's good to know what the hacks are, even if we end up not using them, so this is how you could do that.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now