Believe it or not, you don’t need CSS @media
queries. In this article, learn a few lines of JavaScript that will allow you to mimic the features of @media
queries and build fully responsive websites.
The biggest reason developers don’t opt for inline styles in their React projects is because it lacks some notable CSS features:
:hover
, :first-child
and other pseudo-selectors @keyframe
animations @media
queries
The usual solution is to use CSS-in-JS libraries like styled-components or Radium to get these missing features. It works, however, I think the broader question is, “Are these really valid critiques of inline styles when the argument relies on CSS jargon?”
While JavaScript can’t have :hover
it does have onMouseOver
. Or for @keyframe
… it has the Greensock animation library, or Popmotion. JavaScript can’t have some CSS features, but it’s always had a robust browser-native API.
🐊 Alligator.io recommends ⤵
Fullstack Advanced React & GraphQL by Wes Bos
ⓘ About this affiliate link
If Ya Can’t Beat Em, JavaScript Em
You can even build @media
query-like behavior by just using vanilla JavaScript. It’s incredibly simple.
class Card extends Component { constructor() { super(); this.mediaQuery = { desktop: 1200, tablet: 768, phone: 576, }; this.state = { windowWidth: null }; } componentDidMount() { window.addEventListener('resize', () => { this.setState({windowWidth: document.body.clientWidth}) }); } render() { return ( <div style={{ width: this.state.windowWidth > this.mediaQuery.phone ? '50%' : '100%', //more styling :) }}> <!-- <Card> contents --> </div> ); } }
Check out the live demo!
The important part is document.body.clientWidth
which gives you the width of the browser. Just add a listener for the window “resize” event to update windowWidth
and voilà! There you have it… a fully responsive website!
Advanced 1990s Technology
document.body.clientWidth
has been around for a very long time, yet it’s still useful today for building modern, responsive websites. And you can actually get more mileage from this simple solution.
In this next demo, a low-res image is used for smaller devices to save bandwidth, and desktop devices (larger than 768px) uses a high-res image. This is incredibly simple with JavaScript, whereas it would be quite difficult to tackle with @media
queries.
class ImageGallery extends Component { constructor() { super(); this.mediaQuery = { desktop: 1200, tablet: 768, phone: 576, }; this.state = { windowWidth: null }; } componentDidMount() { window.addEventListener('resize', () => { this.setState({windowWidth: document.body.clientWidth}) }); } render () { const isTablet = this.state.windowWidth < this.mediaQuery.tablet const imgUrl = isTablet ? 'https://picsum.photos/300/300' : 'https://picsum.photos/1200/1200' // 👈 this ternary right here return ( <div> <h1>Mildly Inspirational Photos</h1> <div><img src={imgUrl}/></div> </div> ) } }
This is just one example that shows how versatile a JavaScript-driven solution can be. In fact, you can do a lot of other stuff that @media
queries aren’t able to, like:
- Show React components that are crafted specifically for smaller screens
- Show a modal to download the native iOS app
- Block specific routes that don’t work on a targeted device
We're using the Bootstrap breakpoints here, but you can tailor this for your project's needs.
Conclusion
Try out this JavaScript-driven solution! Inline styles are surprisingly flexible, and in some cases provide more expressive power than CSS.
🌠 See the demo for a more robust implementation that uses the Context API to store the browser width, as well as applying a throttle to the "resize" listener.