14

Is there an alternative for @media queries to accomplish font-size inversely proportional to the screen size? (e.g.: opposite effect of 2vw, where the font gets smaller on small screens);

My first try was divide a value by a viewport width increment, but font-size: calc(10vw / 2); works while font-size: calc(100 / 2vw); unfortunately doesn't works.

codepen of my first try

L777
  • 7,719
  • 3
  • 38
  • 63
  • 1
    because you can't divide by "not a number". Dividing a dimension value by a number works because 10vw, divided by two, is necessarily 5vw. However, what would dividing 10 by 2vw do? The result would be 5/vw, or "5 times the value 1/vw", which makes no sense. – Mike 'Pomax' Kamermans Mar 14 '16 at 19:30
  • thanks for the comment, Mike; its more clear now. My objective was use the `calc()` method to let the font size inversely proportional to the screen size (font bigger on mobile, smaller on desktops) but seems like it's impossible on this way. – L777 Mar 14 '16 at 19:57
  • What do you want the final value to be... 50vw??? – Aziz Mar 14 '16 at 20:35
  • No, I was thinking in something like... 50vw of a 1000px screen means 500px; while 50vw of a 500px screen means 250px; So a number divided by a vw increment would be smaller on big screens. – L777 Mar 14 '16 at 20:40
  • Not quite sure what you mean with that - do you want the font to get smaller, the larger the screen is? (is there a reason why absolute units like `in` or `cm` wouldn't work there?) – Mike 'Pomax' Kamermans Mar 14 '16 at 20:56
  • yes, can you give me an example, please? I mean, a `calc()` one without to use @media queries. – L777 Mar 14 '16 at 21:00
  • Why would you ever want to avoid media queries? This is literally what they are for – Zach Saucier Mar 28 '16 at 02:13

6 Answers6

14

You can't divide a px value by a viewport-width increment, but you can achieve this inverse size behavior reducing a px value by a viewport-width increment.

Example:
font-size: calc(40px - 2vw);

Codepen DEMO

Alternatively, you could use the other 3 units related to the viewport's size: vh vmin and vmax.

Examples:
font-size: calc(40px - 2vh);
font-size: calc(200px - 20vmin);
font-size: calc(200px - 20vmax);

vw - Relative to 1% of the width of the viewport*;
vh - Relative to 1% of the height of the viewport*;
vmin - Relative to 1% of viewport's* smaller dimension;
vmax - Relative to 1% of viewport's* larger dimension;

*viewport = the browser window size.

Source: w3schools

L777
  • 7,719
  • 3
  • 38
  • 63
  • I found this solution just right now. Anyway, there's still an open bounty on the question so new ideas/infos are welcome. – L777 Mar 23 '16 at 08:42
  • 1
    The advantage with my answer would be that you can have a min/max size, and with a very small performance hit, as it only target one item. – Asons Mar 23 '16 at 18:39
2

By definition, a vw is 1/100th of the width of the viewport. That's it. 2vw = 2/100ths of the screen. There is no way to get it to be inversely proportional because math doesn't work that way. I am assuming you are doing this as a thought experiment, rather than trying to solve a problem in your code so I'm going to leave it at that.

You could calculate the size of the font to be inversely proportional via javascript. Here's a codepen

HTML:

<div >
    This is text
</div>

JS:

$(window).resize(function() {
    area = 50000;
    width = $(window).width();
    fontSize= (Math.ceil(area/width));
    $('div').css('font-size', fontSize);
    }).resize();
tayvano
  • 1,308
  • 1
  • 11
  • 18
1

I think that the best that you can do is to use a font size that is not relative to a viewport. For example, 1em will be relatively large on a mobile device and will relatively small on a desktop client. If you use a fluid layout, em is perfect. If you use a static layout, your best option would probably be px. But using px is a bit iffy because a mobile device could potentially have just as many pixels as a desktop client.

The reason that calc(10vw / 2) works but calc(100 / 2vw) doesn't is because the former evaluates to 5vw and the latter evaluates to 50/vw which isn't an expression of distance. More precisely, the engine can only divide by scalar

In summation, to do what you want to do, you'll need to have a fluid layout and use em as your unit for font sizes. But you won't be able to get a direct ratio of the size of the viewport without JavaScript, which you should of course generally not rely on for layout purposes.

Tyler Crompton
  • 12,284
  • 14
  • 65
  • 94
1

Here is a script solution (even if you wanted, and found, a CSS only), though this one impact the performance very little and only need to run once per resize and for one element only, the body.

It has one benefit over CSS, you can have a min/max size, and works as a progressive enhancement for users that have script enabled so in a way risk free.

var fontMax = 40, fontMin = 14;

function sizeBodyFont() {
  var fontSize = ((screen.width / window.innerWidth) * 10);
  document.body.style.fontSize = Math.min(Math.max(fontSize,fontMin),fontMax) + 'px';
}

sizeBodyFont();

(function(el) {
  window.addEventListener('resize', sizeBodyFont);  
}(document.querySelector('#test')))
body {
  font-size: 20px;
}
span {
  font-size: 100%;
}
div {
  font-size: 150%;
}
<span>Hey there</span>
<div>Hey there</div>
Asons
  • 84,923
  • 12
  • 110
  • 165
  • 1
    **bounty reasons**: **a**) plain javascript is more than the goal (css-only) but is lighter than jQuery. **b**) the wrong information was striked and the answer is updated **c**) the example on the snippet works very well. – L777 Mar 30 '16 at 06:52
0

You can use relative font-styling. like -

html, body {
font-size: 16px;
}

h1 {
font-size: 2.5em;
}

p {
font-size: 1em;
}
Pankaj Bisht
  • 986
  • 1
  • 8
  • 27
0

You can achieve this by using css clamp

Here is an awesome github project that can help you: https://clamp.font-size.app/

You'll need to switch the values for max & min to make it work, see example:

body {
  font-size: clamp(1rem, 5.1241rem + -5.6206vw, 4rem);
}
<p>I scale at smaller viewport widths!</p>