0

Let's say I define a CSS variable --half to be equal to 50%.

:root {
  --half: 50%;
}

Then I can set the width of something to be 50% like this:

.partial {
  width: var(--half);
}

So far so good. Let's say that I have a tall element that I want to fill the viewport vertically:

.tall {
  height: 100vh;
}

Great. Finally I want my tall element to only fill up half the vertical space (i.e. 50vh) if partial is used. So I tried this:

.tall.partial {
  height: calc(100vh * var(--half));
}

Oops, that doesn't seem to work. It does work if I redefine --half to equal 0.50:

:root {
  --half: 0.50;
}

But then my width setting above won't work using the variable by itself.

Question Part A: How can I use a XX% designation in a CSS calc() expression and have it be interpreted as the percentage value as a factor in multiplication?

Question Part B: If this can't be done, is there a way I could define the percentage value in terms of the actual value or vice versa, such as the following fictitious definition? (I'd rather not define duplicate, "mirrored" values, one in percentages and one in decimal point values.)

:root {
  --half-factor: 0.50;
  --half: calc(var(half-factor) * 100)%;
}
Garret Wilson
  • 18,219
  • 30
  • 144
  • 272
  • Multiplying by a percentage width does not make sense. What would the resultant unit? 50vh%? – Salman A Sep 07 '20 at 18:24
  • You are thinking of the CSS percent unit. I am wanting to multiply by the percent value, which is unitless; that is, 50% is equivalent to 0.50. They are different representations of the same value. So maybe that's the problem; CSS considers percents a type of unit, and I'm trying to use the value as dimensionless in cases in which there is already a unit in the expression. – Garret Wilson Sep 07 '20 at 18:29

2 Answers2

2

Consider the unit as a variable and you can do it like below:

:root {
  --quarter:25;
  --half:50;
  --threeQuarter:75;
}
* {
   --quarter-R:calc(var(--quarter) * var(--u,1%));
   --half-R:calc(var(--half) * var(--u,1%));
   --threeQuarter-R:calc(var(--threeQuarter) * var(--u,1%));
}

.box {
  height:50px;
  background:red;
  margin:5px;
  width:var(--half-R);
}
<div class="box"></div>

<div class="box" style="--u:1vw"></div>
<div class="box" style="--u:1vw;width:var(--threeQuarter-R);"></div>
<div class="box" style="--u:1vw;width:var(--quarter-R);"></div>
<div class="box" style="--u:1vh"></div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
0

If I'm forced to define two separate variables (Part B of the question), it appears I can do this:

:root {
  --half-factor: 0.50;
  --half: calc(100% * var(half-factor));
}

So that will make my application work and have the values ultimately depend on one value definition (here --half-factor). But if there is a way to pull off both use cases with a single definition, I'd be interested in knowing it. (I know that I can inline calc(100% * var(half-factor)) instead of using var(--half) but that's not what I mean by "single definition".)

Garret Wilson
  • 18,219
  • 30
  • 144
  • 272
  • Yeah, that's pretty much the best I could come up with too: [demo](https://jsfiddle.net/davidThomas/hzqkraje/); though my own approach is based on multiple variables being used together to determine the eventual sizes). – David Thomas Sep 07 '20 at 18:16