How to Format your React App for Mobile

Styling tips to make your app work for any screen size

These days, it's increasingly common for employers to review applications on their mobile devices. Ensuring your application works seamlessly across various screen sizes is essential.

Fortunately, React, JavaScript, and CSS offer a range of tools that make adapting to different devices straightforward.

This article will explore the following methods that can be used to effectively implement these solutions:

  1. Take advantage of conditional rendering

  2. Use styled components with props

  3. Use media queries in CSS/styled components

  4. Use clamp for sizing

  5. Set max values values based on viewport

  6. Use grid-template-columns for repeated elements

How will my components know if I’m using a Mobile Device?

» Use a React Context Provider to determine if the screen width is below a certain threshold

Step 1: Create a Provider with createContext. The window width context below looks at the current window size and returns true if the screen has a width below 768.

import React, { createContext, useContext, useState, useEffect } from 'react';

const WindowWidthContext = createContext();

const WindowWidthProvider = ({ children }) => {
  const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);

  useEffect(() => {
    const handleResize = () => setIsMobile(window.innerWidth <= 768);
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  // Pass an object with isMobile to match usage
  return (
    <WindowWidthContext.Provider value={{ isMobile }}>
      {children}
    </WindowWidthContext.Provider>
  );
};

export { WindowWidthProvider, WindowWidthContext };

Step 2: Wrap your main content in the provider to create context for all your routes

import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { createHashRouter, RouterProvider } from 'react-router-dom'; // Import HashRouter
import routes from './routes'; // Import your routes configuration
import { WindowWidthProvider } from './context/windowSize';

// Create the hash-based router
const router = createHashRouter(routes);

// Create the root and render the app with the router
const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <StrictMode>
    <WindowWidthProvider>
      <RouterProvider router={router} />
    </WindowWidthProvider>
  </StrictMode>,
);

Step 3: Use the newly created context in your component to find whether or not the current window is smaller than the pre-defined threshold. We can then store this boolean value as ‘isMobile’ in any components to use for conditional rendering and/or conditional CSS rules (described in the next sections).

import React, {useContext} from 'react';
import NavBar from "./NavBar"
import MobileNavBar from './MobileNavBar';
import {WindowWidthContext} from "../context/windowSize";

const Header = () => {
  const { isMobile } = useContext(WindowWidthContext);

..

Using this setup, the value of isMobile will re-calculate every time the screen size changes. That way, if you reduce the viewport width of the application on your computer past the threshold, the site will switch to the mobile view automatically.

Tip #1: Take advantage of conditional rendering

In some cases no matter how much you tweak the styling rules, a certain component of your application just won’t work well for smaller screens. In these situations, conditional rendering in React can help to either switch out a component for another, or hide it completely.

One common example of this is a navigation pane. On larger screens, navigation bars often show all the tabs separately across the page, whereas mobile versions of the same site will have a ‘hamburger menu’ that drops down. This functionality can be achieved by rendering the appropriate component based on the window size, as shown in the example below.

...

import {WindowWidthContext} from "../context/windowSize";

const Header = () => {
  const { isMobile } = useContext(WindowWidthContext);

    return (
        <header>
          {isMobile ? <MobileNavBar /> : <NavBar />}
        </header>
    );
}

export default Header;

Alternatively, you can limit mobile functionality by rendering certain components only if the screen size is large enough. One example where this may be used is a sidebar that would otherwise take up too much room on a narrow window.

                {!isMobile && 
                    <SideBar
                        filterInput={filterInput}
                        setFilterInput={setFilterInput}
                    />
                }

Tip #2: Use styled components with props

Props inside styled components are another great way to adjust styling for different screen sizes. You can use this method to apply a certain style based on the window size. In the example below, props are used to apply a margin only for larger screens.

const StyledMain = styled.main`
  .main-content {
    margin: ${(props) => props.isMobile ? '0px' : '20px'};
  }
`;

Tip #3: Use media queries in CSS/styled components

Media queries in CSS will also allow you to set styling rules based on the size of the screen. The example below sets the flex direction to row for larger screens so that elements are shown side by side, but switches to column for smaller screens to show those same elements top to bottom.

const StyledArticle = styled.article`
    display: flex;
    flex-direction: row;

    @media screen and (max-width: 768px) {
        flex-direction: column;
    }
`;

Tip #4: Use clamp for sizing

In CSS, you can use clamp for setting minimum, default, and maximum sizes. In the example below, this function is used to set the default font sizes in the application. This helps to make sure the font does not become too small for mobile screen or too large for very large screens. This ensures readability across all devices.

:root {
  --default-font-size: clamp(0.7rem, 1.7vw, .9rem);
}

h1 {
  font-size: clamp(1.4rem, 3.5vw, 2rem);
}

h2 {
  font-size: clamp(1rem, 3vw, 1.5rem);
}

h3 {
  font-size: clamp(.9rem, 2vw, 1.25rem);
}

p, label, i, li, a {
  font-size: var(--default-font-size)
}

Tip #5: Set max values based on viewport

Applying minimum, default, and maximum widths to components is a simple way to enhance your app's visual appeal across different screen sizes. By using relative units like viewport width (vw) or percentages (%) instead of fixed units like pixels (px), you can ensure that components adapt fluidly and do not extend beyond the screen boundaries.

const StyledForm = styled.form`
  width: 700px;
  min-width: 40vw;
  max-width: 90vw;
`

Tip #6: Use grid-template-columns for repeated elements

Formats like grid-template-columns with auto-fit enable your app to automatically adjust the size and layout of elements based on the specified minimum and maximum widths. The example below demonstrates how this setting can dynamically adjust the number of columns or rows in a container based on these parameters.

.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}

Conclusion

An attractive, responsive design improves user experience and leaves a strong impression on potential employers. These are just a handful of ways to get your application to be visually appealing for different screen sizes.

When building out your app, make sure to test it out on as many screen sizes as possible!

While visual optimization is a good first step for building out your mobile app, it is also essential to consider the technical performance when you need to scale your application. For advice on improving performance in your mobile application, check out:

https://uxcam.com/blog/how-to-improve-mobile-app-performance/