Developer conducting responsive design across multiple screens with a cat observer

Orchestrating Responsive UIs with React Media

The Gray Cat
The Gray Cat

React Media is a powerful library that brings the harmony of CSS media queries directly into your React components. It allows developers to compose responsive and adaptive user interfaces without the need for complex CSS or JavaScript orchestrations. By leveraging the power of media queries within your React code, you can easily adjust your application’s layout and functionality based on screen size, device orientation, or other media features, creating a symphony of responsive design.

Features

  • CSS Media Query Integration: Utilize standard CSS media queries directly in your React components.
  • Object-based Query Syntax: Compose media queries using JavaScript objects for enhanced readability and maintainability.
  • Multiple Query Support: Harmonize multiple media queries simultaneously.
  • Server-Side Rendering Compatibility: Seamlessly blend with server-side rendering setups.
  • Render Props API: Flexible rendering options to orchestrate various use cases.

Installation

To begin your responsive design symphony with React Media, you can install it via npm or yarn:

Using npm:

npm install react-media --save

Using yarn:

yarn add react-media

Basic Usage

Single Query Component

Let’s start with a simple melody that demonstrates how to use React Media with a single query:

import React from 'react';
import Media from 'react-media';

const ResponsiveComponent: React.FC = () => {
  return (
    <div>
      <Media query="(max-width: 599px)">
        {matches =>
          matches ? (
            <p>The viewport is playing a soft, narrow tune</p>
          ) : (
            <p>The viewport is resonating with a wide melody</p>
          )
        }
      </Media>
    </div>
  );
};

In this composition, we’re using the Media component with a query prop that checks if the viewport width is 599px or less. The component’s children function receives a matches boolean, which we use to conditionally render different content based on whether the media query matches or not, creating responsive harmony.

Using Object Syntax

React Media also supports an object-based syntax for defining media queries, which can create more readable and maintainable compositions:

import React from 'react';
import Media from 'react-media';

const ObjectSyntaxExample: React.FC = () => {
  return (
    <Media query={{ maxWidth: 599 }}>
      {matches =>
        matches ? (
          <p>The viewport is playing a soft, narrow tune</p>
        ) : (
          <p>The viewport is resonating with a wide melody</p>
        )
      }
    </Media>
  );
};

This example is equivalent to the previous one, but uses an object to define the media query. React Media automatically transposes this object to a valid CSS media query string.

Advanced Usage

Multiple Queries

React Media allows you to orchestrate multiple queries simultaneously using the queries prop:

import React from 'react';
import Media from 'react-media';

const MultiQueryComponent: React.FC = () => {
  return (
    <Media queries={{
      small: "(max-width: 599px)",
      medium: "(min-width: 600px) and (max-width: 1199px)",
      large: "(min-width: 1200px)"
    }}>
      {matches => (
        <div>
          {matches.small && <p>Small viewport: A delicate solo performance</p>}
          {matches.medium && <p>Medium viewport: A chamber music arrangement</p>}
          {matches.large && <p>Large viewport: A full orchestral experience</p>}
        </div>
      )}
    </Media>
  );
};

This component defines three different breakpoints and renders content based on which queries match, creating a responsive ensemble. The matches object passed to the children function contains boolean values for each defined query.

Render Props

React Media supports multiple ways to conduct your content based on media queries. Here’s an example using the render prop:

import React from 'react';
import Media from 'react-media';

const RenderPropExample: React.FC = () => {
  return (
    <Media
      queries={{
        small: "(max-width: 599px)",
        large: "(min-width: 600px)"
      }}
      render={() => <p>The responsive symphony has begun!</p>}
    />
  );
};

The render prop is a function that only gets called when at least one of the specified queries matches. This can be useful when you want to orchestrate content only under certain conditions.

Server-Side Rendering

When composing with React Media in a server-side rendering environment, you can use the defaultMatches prop to set the initial state:

import React from 'react';
import Media from 'react-media';

interface ServerSideProps {
  userAgent: string;
}

const ServerSideExample: React.FC<ServerSideProps> = ({ userAgent }) => {
  const isMobile = /mobile/i.test(userAgent);

  return (
    <Media
      query="(max-width: 599px)"
      defaultMatches={isMobile}
      render={() => <p>This content is tuned for small screens.</p>}
    />
  );
};

By providing a defaultMatches value, you can ensure that the initial render on the server harmonizes with what you expect the client-side result to be, based on information like the user agent string.

Using with Custom Windows

In some compositions, you might need to evaluate media queries against a different window object, such as when rendering content in an iframe. React Media supports this arrangement with the targetWindow prop:

import React, { useRef, useEffect, useState } from 'react';
import Media from 'react-media';

const IframeExample: React.FC = () => {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [iframeWindow, setIframeWindow] = useState<Window | null>(null);

  useEffect(() => {
    if (iframeRef.current) {
      setIframeWindow(iframeRef.current.contentWindow);
    }
  }, []);

  return (
    <div>
      <iframe ref={iframeRef} src="about:blank" />
      {iframeWindow && (
        <Media
          query="(max-width: 599px)"
          targetWindow={iframeWindow}
          render={() => <p>The iframe content is performing a narrow melody</p>}
        />
      )}
    </div>
  );
};

This example demonstrates how to use the targetWindow prop to evaluate media queries against the window of an iframe, allowing for responsive compositions within embedded contexts.

Conclusion

React Media provides a powerful and flexible way to compose responsive designs directly into your React components. By harmonizing CSS media queries with React’s component-based architecture, you can create adaptive user interfaces that provide optimal experiences across a wide range of devices and screen sizes.

Whether you’re orchestrating a complex web application or composing a simple responsive website, React Media offers the instruments you need to implement sophisticated responsive logic with ease. Its support for server-side rendering and advanced use cases like iframe targeting make it a versatile choice for projects of any scale.

As you continue to explore the melodies of React Media, you’ll discover even more ways to enhance your application’s responsiveness and user experience. May your responsive designs always be in perfect harmony!

Comments