Paulo
Paulo

Reputation: 571

Inline CSS styles in React: how to implement media queries?

I quite like the inline CSS pattern (video) in React and i am thinking about using it. However i have a question similar to this one.

How does one go about implementing media queries for an application using React's inline CSS pattern.

Upvotes: 57

Views: 100674

Answers (7)

Resfe
Resfe

Reputation: 57

You can use Box Component from Chakra UI, it will let you define a CSS prop and through that you can specify your media queries.

    <Box
            height={"auto"}
            backgroundColor={"#F7F8FA"}
            width={"400px"}
            css={{
                '@media (max-width: 1280px)': {
                    width: "380px",
                },
            }}
        > </Box>

Upvotes: -2

Stan
Stan

Reputation: 2048

Im late to the party but I still hope that I can help. You can use a "useMediaQuery" hook and then apply inline styles dynamically if the hook returns true.

const useMediaQuery = (query) => {
  const [matches, setMatches] = useState(false);

  useEffect(() => {
    const media = window.matchMedia(query);
    if (media.matches !== matches) {
      setMatches(media.matches);
    }
    const listener = () => setMatches(media.matches);
    window.addEventListener("resize", listener);
    return () => window.removeEventListener("resize", listener);
  }, [matches, query]);

  return matches;
}

export default useMediaQuery;

Upvotes: 2

Bashid
Bashid

Reputation: 520

Worked for me below handy steps:

  1. set a class for your desire item in media css file, for example

    @media (max-width: 768px){
    .sidebar-show{
        display: block;
     }
     .sidebar-hide{
        display: none;
     }}
    
  2. conditional rendering in your react, for example:(showSideBar is state variable for example)

    <aside className={`col-md-3 ${showSideBar?"sidebar-show":"sidebar-hide"}`}>
    

Upvotes: 3

Alex
Alex

Reputation: 81

You can use media queries with the radium package by simply importing it and also using the StyleRoot component.

import Radium, { StyleRoot } from 'radium';

However keep it in mind, you can not use media queries directly under StyleRoot

, you will have to put the contents of StyleRoot on a separate component

Upvotes: 0

Kat
Kat

Reputation: 1654

React-Responsive will let you use a certain use-case of media queries.

It lets you wrap react element elements with media specifications. The wrapped elements will be rendered only if they media specification is met. It's not a general-purpose solution because it doesn't let you add arbitrary css properties.

Upvotes: 8

Mark
Mark

Reputation: 41175

You can't. There are certain CSS features, like @media queries, that must be defined in a declaration block in a stylesheet.

While inline CSS is great for most styling attributes that can be applied in key-value pairs, it isn't a complete replacement for dedicated stylesheets.

EDIT:

There are experimental objects available in certain browsers (Chrome 9+, IE 10+, Firefox 6+) that allow you to add event listeners when media queries on the document change, such as MediaQueryList.

There is a nascent React project called Radium that provides mixins for applying conditional styling based on the active media queries, using MediaQueryList under the hood.

Upvotes: 41

Brigand
Brigand

Reputation: 86270

You can't do things like media queries and pseudo elements without a stylesheet. You can, however, access the information they're built on in JavaScript. For example, a naive implementation of a resize mixin:

var ResizeMixin = {
    componentDidMount: function(){
        window.addEventListener('resize', this._resize_mixin_callback);
    },
    _resize_mixin_callback: function(){
        this.setState({
            viewport: {
                width: document.documentElement.clientWidth,
                height: document.documentElement.clientHeight
            }
        });
    },
    componentWillUnmount: function(){
        window.removeEventListener('resize', this._resize_mixin_callback);
    }
};

You could then include that in your component, and have a render that looks like this:

render: function(){
  var style;

  if (this.state.viewport.width > 900) {
    style = {width: '45%', margin: '2.5%'};
  }
  else {
    style = {width: '100%', margin: '0'};
  }
  ...
}

I'm not sure this is a good idea, but it can be done.


By 'naive implementation' I mean it has performance problems. addEventListener is actually pretty heavy, so you want to wrap that in a simple js event emitter. You can also have only one instance of the viewport object to save some GC pressure. And you want to throttle the event because browsers will emit it very fast when dragging the window.

As with all good abstractions, you can make these optimizations when you have spare time, and you don't need to modify the components using it.

Upvotes: 19

Related Questions