CSS Type Casting to Numeric: tan(atan2()) Scalars

By admin
In current browser implementations of

CSS
ORG

, you cannot divide by length types;

calc(100vw / 5px
ORG

) does not work. It will eventually because it’s in the spec, and with enough support it may happen soon. But for now, no way to produce scalars based on size.

With, technically, one up-and-coming exception,

atan2
ORG

() .


atan2
ORG

() accepts

2
CARDINAL

params, effectively the slope, rise over run, y divided by x, atan2(height, width) and returns the angle from the bottom of the slope looking to the top.

Then, did you know? tan(atan2(height, width)) is the scalar <number> between the

two
CARDINAL

dimensions.

No, I did not know that; is that true?

That’s right… One could scale all kinds of dimensions, using simple trigonometry functions.

Really…?

If one were so inclined.

tan(atan2()) is just a scalar

No need to dive into normal trig things; pretty graphs, maps, and geometric art, etc.

Fundamentally, tan(atan2()) is just a scalar between

two
CARDINAL

dimensions.

For this article I’ll focus on identity scaling as a means to typecast into a numeric value but there are many ways to use this and compare any

two
CARDINAL

dimensions now.


Screensize
PERSON


One
CARDINAL

thing many people want is the ability to have the numeric pixel width (or height) of the viewport to find the aspect-ratio or do other calcs down the line.

I solved screensize in

100%
PERCENT

CSS previously with a binary search using The CPU Hack but I realized

today
DATE

it’s so much easier and faster with tan(atan2()) :

What is the numeric pixel value of

100vw
LOC

?

should be as easy as

:root { –px-width : tan (

atan2
ORG

(

100vw
LOC

, 1px )); } Enter fullscreen mode

Exit
PRODUCT

fullscreen mode

but

atan2
ORG

is super buggy in browsers right now. (mixing vw and px was intended to work)


Chrome
PERSON

returns

100
CARDINAL

in this case, which is strange/undesirable. Firefox returns

0
CARDINAL

in this case because of the mixed units failing. If both are vw or both are px ,

Firefox
ORG

correctly returns

100
CARDINAL

.

Safari
ORG

seems to always return

0
CARDINAL

from tan(atan2(Y, X)) for any Y and any X . With or without units, mixed or matching. (edit: Unless you wrap it in calc())

So for now we

first
ORDINAL

need

100vw
LOC

as

NNNpx
ORG

, which is easy in CSS because that’s what happens automatically if you register a var as <length> then set it to a value like –100vw:

100vw

PRODUCT

@property –100vw { syntax : "<length>" ; initial-value : 0px ; inherits : false ; } Enter fullscreen mode

Exit
PRODUCT

fullscreen mode

Now this works in

Chrome
ORG

exactly as hoped:

:root { –100vw :

100vw
LOC

; –px-width : tan ( atan2 ( var ( –100vw ), 1px )); } Enter fullscreen mode

Exit
PRODUCT

fullscreen mode

–px-width is the width of the screen as a, usually integer, number

here it is live including one for

100vh
PERSON

too:

get font-size and more

You can use this same idea for any container query units, calc sizes containing mixed units, find out the px size of rem, anything you want. Just register a length, set its value, and convert to numeric px with tan(atan2()) .

Easy peasy! Potentially super useful.

Works with <time> too

:root::after { –ms : tan (

atan2
ORG

( 12s + 1ms , 1ms )); counter-reset :

val var ( –ms
PERSON

); content : "Numeric ms value of

12s
CARDINAL

+ 1ms is: " counter ( val ); /* counter prints

12001
CARDINAL

*/ } Enter fullscreen mode

Exit
PRODUCT

fullscreen mode

That’s all numeric typecasting identity scalars, and it’s fun to think about all the ways you can mix calcs now, but there’s even more cool stuff tan-atan2 can-a-can-do, perhaps for a future article ~

The Trig (update)

The trig behind this isn’t necessary to know to use it, but I had a couple questions come up in private about it:

tan( angle ) is a function that takes an angle then produces a result that’s equal to "opposite over adjacent" – the height divided by the width of a right triangle:

atan( ratio ) is a function that takes the value of height divided by width and returns the angle; the inverse of tan() .


atan2
PERSON

( Y, X ) is a programming language’s adaptation of

atan
ORG

() that takes the height (Y) and width (X) as separate arguments instead of dividing them before passing, then returns the same thing

atan
ORG

would have.

So what this trick is doing is kind of silly in most worlds (and probably why nobody pointed it out sooner) because we’re using

two
CARDINAL

trig functions instead of division that calc() implementations can’t do yet.


atan2
PERSON

( Height,

Width
PERSON

) = angle from the picture above tan( angle ) =

Height / Width
PERSON

from the picture above tan( atan2( Height,

Width
PERSON

) ) =

Height / Width
ORG

@property –MyFullInlineSize { syntax : "<length>" ; initial-value : 0px ; inherits : false ; } @property –MyEm { syntax : "<length>" ; initial-value : 0px ; inherits : false ; } div .in-a-container { –MyFullInlineSize :

100
CARDINAL

cqi ; –MyEm : 1em ; –MyNumEmsWide : tan ( atan2 ( var ( –MyFullInlineSize ), var ( –MyEm ) )); –MyNumPxWide : tan ( atan2 ( var ( –MyFullInlineSize ), 1px )); } Enter fullscreen mode

Exit
PRODUCT

fullscreen mode

The End

If you think this is useful, fun, or interesting, it’s the kind of thing I do in my free time! So please do consider following me around the web:

PropJockey.io CodePen DEV Blog GitHub Mastodon

and

𝕏@Jane0ri
ORG

👽💜

//

Jane Ori

PERSON

PS: I’ve been laid off recently and am looking for a job!

https://linkedin.com/in/JaneOri

Over

13 years
DATE

of full stack (mostly JS) engineering work and consulting, ready for the right opportunity!