Unlock the Power of Responsive Design with Fresnel

Why Responsive Design Matters

In today’s digital landscape, providing an exceptional user experience (UX) is crucial for any web application. With the majority of users accessing websites through mobile devices, tablets, and desktops, responsive design has become a must-have in modern web development.

What are CSS Media Queries?

Media queries allow developers to define different styling rules for various viewport sizes. Traditionally, we create HTML elements and then use CSS to describe how they’ll behave on different screen widths via media queries.

/* Example of a media query */
@media only screen and (max-width: 480px) {
  /* Styles for screen widths up to 480px */
 .square-element {
    background-color: blue;
  }
}

Introducing Fresnel

Fresnel revolutionizes the traditional media query approach by transferring its breakpoint logic to the React ecosystem. This open-source npm project, created by Artsy, is easy to use and trusted by developers worldwide. Fresnel’s API enables us to use MediaContextProvider and Media components to build a solid foundation for responsive web applications.

Fresnel vs Conditional Rendering

While conditional rendering works fine for client-side rendering, it falls short when implementing server-side rendering (SSR) solutions. Fresnel shines by rendering all breakpoints on the server, allowing us to properly render HTML/CSS before React has booted. This significantly improves the UX for users.

Building a Responsive App with React and Fresnel

Let’s create a color card application that switches its layout for mobile and desktop views. We’ll use Fresnel to render the breakpoints on the server, ensuring a seamless UX.

Initializing the React App

We’ll start by creating a new project folder and initializing a new React project using npm init -y. Next, we’ll install the necessary dependencies, including Express for the backend and Fresnel for responsive design.

npm init -y
npm install express fresnel

Modeling Data in React

We’ll separate the data from the app logic by creating a data folder with a colors.jsx file containing an array of color names.

// data/colors.jsx
const colors = [
  'ed',
  'blue',
  'green',
  //...
];

export default colors;

Creating Breakpoints

We’ll define specific breakpoints using the createMedia function and export mediaStyle, which we’ll inject into the server-side.

// media.js
import { createMedia } from 'fresnel';

const { mediaStyle } = createMedia({
  breakpoints: {
    mobile: '(max-width: 480px)',
    desktop: '(min-width: 481px)',
  },
});

export default mediaStyle;

Creating Components

We’ll create four separate files for the DesktopComponent and MobileComponent, along with their respective CSS files. We’ll use grid templates to define the columns and rows for the desktop view and a single-column layout for the mobile view.

/* desktop.css */
.grid-container {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-gap: 10px;
}

/* mobile.css */
.grid-container {
  display: flex;
  flex-direction: column;
}

Implementing Frontend with Fresnel

We’ll create an App component that will render the components based on the viewport size. We’ll use Media and MediaContextProvider to control which components should be displayed on which viewports.

// App.jsx
import React from 'eact';
import { Media, MediaContextProvider } from 'fresnel';
import DesktopComponent from './DesktopComponent';
import MobileComponent from './MobileComponent';

const App = () => {
  return (
    <MediaContextProvider>
      <Media at="mobile">
        <MobileComponent />
      </Media>
      <Media at="desktop">
        <DesktopComponent />
      </Media>
    </MediaContextProvider>
  );
};

export default App;

Setting Up the Backend

We’ll create a server folder with an index.jsx file, using Express to provide the functionality for server-side rendering. We’ll generate HTML on the server and send the markup as a response.

// server/index.jsx
import express from 'express';
import React from 'eact';
import ReactDOMServer from 'eact-dom/server';
import App from '../App';

const app = express();

app.get('*', (req, res) => {
  const markup = ReactDOMServer.renderToString(<App />);
  res.send(`<html><body>${markup}</body></html>`);
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

Configuring Builds

We’ll use esbuild to bundle our files for SSR. We’ll set up scripts in package.json to run the build commands for both the frontend and server files.

// package.json
"scripts": {
  "build:frontend": "esbuild frontend/index.jsx --bundle --outdir=public",
  "build:server": "esbuild server/index.jsx --bundle --platform=node --outdir=server",
  "start": "node server/index.js"
}

Testing the React App

Finally, we’ll run the app using npm start and test it in the browser. We’ll see how the responsive design works seamlessly across different viewport sizes.

  • Run npm start to start the server.
  • Open the app in a browser and resize the window to see the responsive design in action.

Leave a Reply