Search code examples
cssmathcss-calc

Calculating fluid CSS element sizes using CSS using calc(px + vw)


Using this method here: https://css-tricks.com/fun-viewport-units/

I want to calculate how to achieve a specific amount of change between view port sizes 1920px and 375px

Example: I want my element of 150px to reduce in size by 40px between 1920px and 375px

The problem:

I'm not sure what equation I should be using to best define my input values.

I tried taking the desired size of 150px at 1920px adding 40px divided 19.2 (2.083vw) minus 40px:

width: calc(150px + (2.083vw - 40px))

It's very close, but not quite there, just shy of 150px at 1920px, but 117px at 375px.

I also tried using 40px divide by the difference between viewport sizes 15.45:

width: calc(150px + (2.588vw - 40px))

But that was much further away 160px at 1920px and 119px at 375px:

Part solution:

If I fiddle the numbers as seen with the element boxfix it's right (or close eneough not to care about the half px each way)

width: calc(150px + (2.56vw - 49.5px))

As I don't want to have to fiddle the numbers each time I'm hoping there's a way to calculate what the value of each should be with more accuracy, or if there's a better sum I could be using to achieve the same thing.

JS Fiddle:

Here's a JSFiddle in case it's useful: https://jsfiddle.net/8qdptyj3/1/

body {
  font-size: 18px;
}

.box {
  width: calc(150px + (2.083vw - 40px))
}

.boxfix {
  width: calc(150px + (2.56vw - 49.5px))
}
<div class="box" style="background:red;color:white;margin:10px;">
  Hello World
</div>
<div class="boxfix" style="background:red;color:white;margin:10px;">
  Hello World
</div>


Solution

  • You need to solve the equation Y = A*X + B where in your case Y is the width and X is 100vw So width: calc(A*100vw + B)

    When 100vw = 1920px you need width: 150px so we have

    150px = A*1920px + B
    

    When 100vw = 375px you need width: 110px so we have

    110px = A*375px + B
    

    We do some math and we get A = 0.026 and B = 100.3

    Your code is width: calc(0.026*100vw + 100.3px) Also width: calc(2.6vw + 100.3px)


    You can also write it as

    --a: ((150 - 110)/(1920 - 375));
    --b: 150px - 1920px*var(--a);  /* OR 110px - 375px*var(--a) */
    width: calc(var(--a)*100vw + var(--b));
    

    body {
      font-size: 18px;
    }
    
    .box {
      width: calc(2.6vw + 100.3px);
      height: 100px;
    }
    
    .box-alt {
      --a: ((150 - 110)/(1920 - 375));
      --b: 150px - 1920px*var(--a);
      width: calc(var(--a)*100vw + var(--b));
      height: 100px;
    }
    <div class="box" style="background:red;color:white;margin:10px;">
    
    </div>
    
    <div class="box-alt" style="background:red;color:white;margin:10px;">
    
    </div>