PX to VW Converter
Pixels to vw, then the same vw across eight viewport widths so you can see it collapse on a phone, plus the clamp() that stops it.
Pixels 48px
At design width 1920px
In vw 2.5vw
In rem 3rem
2.5vw resolves to
360×800, small phone 9px
390×844, phone 9.75px
768×1024, tablet, portrait 19.2px
1024×768, tablet, landscape 25.6px
1280×800, small laptop 32px
1440×900, laptop 36px
1920×1080, desktop 48px <- your design width
2560×1440, large desktop 64px
Floor at 360px wide 24px
Fluid, with both ends held clamp(1.5rem, 1.1538rem + 1.5385vw, 3rem)
48px at a 1920px design width is 2.5vw. On a 360px phone that same value
renders at 9px, which is 19 percent of what you designed.
vw is a hundredth of the viewport width, and it keeps going in both
directions: there is no floor and no ceiling. That is the whole problem
with it as a type unit, and the reason the table above is longer than
the conversion.
The clamp() holds the size between 24px and 48px and interpolates in
between. The middle term is written as rem plus vw rather than vw alone
so that the value still responds to a reader who has changed their
browser font size; a bare vw ignores that setting completely, which is
an accessibility failure and not only a taste one.
vw includes the scrollbar width on desktop browsers, so 100vw is wider
than the space you can actually use and produces a horizontal scrollbar
on a full-width element. 100% does not have that problem, and neither
does 100dvw in the browsers that support it.
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
Dividing a pixel size by the design width gives you a vw value. That takes one line and it is not the useful part.
The useful part is what that vw becomes everywhere else. 48px at a 1920px design width is 2.5vw, and 2.5vw on a 360px phone is 9px. Type set in vw does not shrink politely, it collapses, and the figure most people check is the one from the design file where it looked fine.
So this converts, shows the value at eight viewport widths, and writes the clamp()
that holds both ends.
How to use
- Put in the pixel size and the design width you measured it at.
- Read the table: that is the same declaration on eight screens.
- Put in a floor for 360px wide, and copy the
clamp().
Example
48px at a 1920px design width, with a 24px floor:
Pixels 48px
At design width 1920px
In vw 2.5vw
In rem 3rem
2.5vw resolves to
360×800, small phone 9px
390×844, phone 9.75px
768×1024, tablet, portrait 19.2px
1024×768, tablet, landscape 25.6px
1280×800, small laptop 32px
1440×900, laptop 36px
1920×1080, desktop 48px <- your design width
2560×1440, large desktop 64px
Floor at 360px wide 24px
Fluid, with both ends held clamp(1.5rem, 1.1538rem + 1.5385vw, 3rem)
9px on a phone is 19 percent of what you designed. Nobody would specify a 9px
heading, and shipping font-size: 2.5vw specifies it by accident.
Pitfalls
A bare vw has no floor and no ceiling. It keeps scaling in both directions, so the same declaration that looks right on your laptop is unreadable on a phone and enormous on a 4K monitor. Clamp it or use rem.
A vw-only value ignores the reader’s font size setting. Someone who has set their
browser to a 24px default gets nothing from font-size: 2.5vw, which is a genuine
accessibility failure rather than a preference. The clamp() this tool writes puts a
rem term in the middle expression, so the value still responds to that setting.
100vw is wider than the space you have. On desktop browsers it includes the
classic scrollbar, so a full-width element in 100vw produces a horizontal
scrollbar. Use 100%, or 100dvw where it is available.
vw is the viewport, not the container. A component inside a 400px sidebar still
sizes its vw against the whole window. If you want the container, that is container
query units: cqw and friends, which have been in every current browser since 2023.
Check the narrow end, not the wide one. Most vw bugs are on small screens, and most previews are taken on large ones. The table here starts at 360px for that reason.
Beware very small vw values on very large screens. At 2560px wide, 1vw is 25.6px, so a 0.5vw gap you fine-tuned on a laptop becomes 13px on a large monitor.
Compatibility
Arithmetic in the browser: nothing is uploaded and nothing is stored. The share link carries the figures and the clamp.
clamp() has been in every current browser since 2020. The pattern written here is
the standard one: a rem minimum, a rem + vw preferred value and a rem maximum. The
middle term is a linear equation through your two points, which means the size moves
in a straight line between the two viewports rather than stepping at a breakpoint.
The interpolation is linear in viewport width, so a clamp() between 360px and
1920px is a little steeper in the middle than a designer’s eye usually wants. If the
midpoint feels large, set the floor a touch higher rather than reaching for a media
query.
The viewport list is a spread rather than a device list. If a value is wrong somewhere, it is wrong somewhere in this range.
Frequently asked questions
Should I use vw for font sizes at all?
clamp(), yes: it is the cleanest way to get type that scales smoothly
between two sizes without breakpoints. On its own, no.What design width should I put in?
Why does the clamp have rem in the middle term?
clamp() with a rem minimum but a
vw-only preferred value is only accessible at the very bottom of its range.What about vmin and vmax?
vmin is a hundredth of the shorter viewport side and vmax the longer. vmin is
useful for something that must fit on screen in either orientation, such as a square
hero image. The general CSS unit converter on this site handles both.Can I use container query units instead?
cqw is a hundredth of the container’s width, which is
what you usually meant. The arithmetic is identical, with the container width in place
of the design width.