How to Redesign Unsplash Using Styled Components

Writing future-proof CSS is hard. Conflicting classnames, specificity issues, and so on, come up when you have to write and maintain thousands of lines of CSS. To get rid of the aforementioned issues, Styled Components was created.

Styled Components makes it easy to write your CSS in JS and makes sure there are no conflicting classnames or specificity issues with multiple other benefits. This makes writing CSS a joy.

In this tutorial, we’ll explore what CSS in JS is, the pros and cons of styled-components, and finally, we’ll redesign Unsplash using Styled Components. After completing this tutorial, you should be able to quickly get up and running with Styled Components.

Note: Styled Components was specifically built with React in mind, so you have to be using React to use Styled Components.

Prerequisites

For this tutorial, you need a basic knowledge of React.

Throughout the course of this tutorial we’ll be using yarn. If you don’t have yarn already installed, then install it from here.

To make sure we’re on the same page, these are the versions used in this tutorial:

  • Node 12.6.0
  • npx 6.4.1
  • yarn 1.17.3

Evolution of CSS

Before CSS-in-JS was created, the most common way to style web apps was to write CSS in a separate file and link it from the HTML.

But this caused trouble in big teams. Everyone has their own way of writing CSS. This caused specificity issues and led to everyone using !important.

Then came Sass. Sass is an extension of CSS that allows us to use things like variables, nested rules, inline imports and more. It also helps to keep things organized and allows us to create stylesheets faster.

Even though Sass might be thought of as an improvement over CSS, it arguably causes more harm than good without certain systems put in place.

Later, BEM came in. BEM is a methodology that lets us reduce specificity issues by making us write unique classnames. BEM does solve the specificity problem, but it makes the HTML more verbose. Classnames can become unnecessarily long, and it’s hard to come up with unique classnames when you have a huge web app.

After that, CSS Modules were born. CSS Modules solved what neither Sass nor BEM could — the problem of unique classnames — by tooling rather than relying on the name given by a developer, which in turn solved specificity issues. CSS Modules gained a huge popularity in the React ecosystem, paving the way for projects like glamor.

The only problem with all these new solutions was that developers were made to learn new syntaxes. What if we could write CSS exactly how we write it in a .css file but in JS? And thus styled-components came into existence.

Styled Components uses Template Literals, an ES6 feature. Template literals are string literals allowing embedded expressions. They allow for multi-line strings and string interpolation features with them.

The main selling point of Styled Components is that it allows us to write exact CSS in JS.

Styled Components has a lot of benefits. Some of the pros and cons of Styled Components are listed below.

Pros

There are lots of advantages to using Styled Components.

  1. Injecting Critical CSS into the DOM

    Styled Components only injects critical CSS on the page. This means users only download CSS needed for that particular page and nothing else. This loads the web page faster.

  2. Smaller CSS bundle per page

    As it only injects styles that are used in the components on the page, bundle size is considerably smaller. You only load the CSS you need, instead of excessive stylesheets, normalizers, responsiveness, etc.

  3. Automatic Vendor Prefixing

    Styled Components allows you to write your CSS and it automatically vendor prefixes according to the latest standard.

  4. Remove unused CSS

    With Styled Components, it’s easier to remove unused CSS or dead code, as the styles are colocated with the component. This also impacts on reducing bundle size.

  5. Theming is easy

    Styled Components makes it really easy to theme a React applications. You can even have multiple themes in your applications and yet easily maintain them.

  6. Reduces the number of HTTP requests

    Since there are no CSS files for resets, normalizers, and responsiveness, the number of HTTP requests are considerably reduced.

  7. Unique Classnames

    Styled Components generates unique classnames every time a build step takes place. This allows avoiding naming collisions or specificity issues. No more having global conflicts and being forced to resolve them with !important tags.

  8. Maintenance is easy

    Styled Components allows you to colocate styles with the component. This allows for painless maintenance. You know exactly which style is affecting your component, unlike in a big CSS file.

Cons

Of course, nothing’s perfect. Let’s look at some downsides associated with Styled Components.

  1. Unable to Cache Stylesheets

    Generally, a web browser caches .css files when a user visits a website for the next visit, so it doesn’t have to download the same .css file again. But with styled-components, the styles are loaded in the DOM using the <style> tag. Thus, they can’t be cached and every time user has to request styles when they visit your website.

  2. React specific

    Styled Components was made with React in mind. Thus, it’s React specific. If you use any other framework, then you can’t use Styled Components.

    However, there’s an alternative very similar to styled-components known as emotion which is framework agnostic.

Getting Practical

Now that we know the pros and cons of Styled Components, let’s start using it.

Go ahead and scaffold a new React project using create-react-app. To scaffold it, we’ll be using npx, which lets you download and run a package temporarily without polluting the global namespace.

Type the following in the terminal:

$ npx create-react-app unsplash-styled-components

Then go inside the unsplash-styled-components directory and install the following packages needed for the purpose of this tutorial, namely styled-components and react-medium-image-zoom:

$ cd unsplash-styled-components
$ yarn add styled-components react-medium-image-zoom

The styled-components package allows us to write actual CSS in JS while the react-medium-image-zoom package allows us to zoom in on an image Medium-style.

Now, once the installation is complete, delete unneeded files like App.css, App.test.js, index.css and logo.svg from the src/ directory.

Go ahead and remove import './index.css'; from index.js, as it’s no longer needed.

Replace the contents of App.js with the following:

import React from 'react'

const App = () => <h1>Hello React</h1>

export default App

Try running the development server now by typing yarn start in the terminal.

You should see Hello React printed on the screen like this:

Hello React

Styled Components uses tagged template literals to style your component.

Let’s suppose you want to style the h1 as white text on a pink background by using Styled Components. Here’s how you would do it:

import React from 'react'
import styled from 'styled-components'

const Header = styled.h1`
    background-color: pink;
    color: white;
`

const App = () => <Header>Hello React</Header>

export default App

It should now look like this:

Hello React using Styled Components

We just created our first Styled Component Header. The Header component is assigned to styled.h1. The default export styled coming from styled-components has basic HTML primitives like div, span, h1, h2, etc.

Inside of styled.h1 we write the actual CSS. Notice how we’re writing CSS rather than making style objects.

Furthermore, the Header component gets replaced in the browser with an h1 tag and a unique classname. A style tag gets inserted into the DOM with the same unique classname. This is the basics of how Styled Components actually work.

Our styles are in the same file as our component. This means our component is co-located with styles. Thus, it’s easier to remove styles associated with a particular component, thereby eliminating dead code.

Traditionally in CSS, it’s hard to reason about, as we have to find a particular element’s classname or id or specific selector, then remove them one by one. It’s easy in a small project, but it gets hard as the project complexity increases. With Styled Components, no matter the complexity of the project, it’s easier to add, edit and remove styles, as they’re colocated with the component.

Theming in Styled Components

Let’s add theming to our project.

Create a utils/ folder in the src/ directory. Then create a themes.js file in the utils/ folder. Paste the following in themes.js:

export const themes = {
  common: {
    fontFamily:
      "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
  },
  light: {
    type: 'light',
    bgColor: 'white',
    color: '#3E4C59',
    searchBgColor: '#E4E7EB',
    boxShadow: '0.8rem 0.8rem 1.5rem gray',
    categoryColor: '#999',
    categoryHoverColor: '#333',
  },
  dark: {
    type: 'dark',
    bgColor: '#1F2933',
    color: '#E4E7EB',
    searchBgColor: '#E4E7EB',
    boxShadow: '0.4rem 0.4rem 1.5rem #111111',
    categoryColor: '#CBD2D9',
    categoryHoverColor: '#9AA5B1',
  },
}

The themes.js file contains an object named themes with three properties: common, light and dark.

The common property contains common styles across themes, the light property contains styles for the light theme, and the dark property contains styles for the dark theme.

Now change App.js as follows:

import React, { useState } from 'react'
import styled, { ThemeProvider } from 'styled-components'
import { themes } from './utils/themes'

const lightTheme = () => ({
  ...themes['common'],
  ...themes['light'],
})

const darkTheme = () => ({
  ...themes['common'],
  ...themes['dark'],
})

const Header = styled.h1`
    background-color: pink;
    color: white;
`

const App = () => {
  const [theme, setTheme] = useState(lightTheme())
  const setDarkTheme = () => setTheme(darkTheme())
  const setLightTheme = () => setTheme(lightTheme())
    return (
        <ThemeProvider theme={theme}>
            <>
                <Header>Hello React</Header>
                <button onClick={setLightTheme}>Make it light</button>
                <button onClick={setDarkTheme}>Make it dark</button>
            </>
        </ThemeProvider>
    )
}

export default App

Firstly, we’ve imported the useState hook from react, ThemeProvider from styled-components and themes from ./utils/themes.

Then we’ve created two arrow functions, lightTheme and darkTheme.

The lightTheme function returns an object combining the common and light properties from the imported themes variable.

So basically, the lightTheme function after evaluation is this:

const lightTheme = () => ({
    fontFamily:
        "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
    type: 'light',
    bgColor: 'white',
    color: '#3E4C59',
    searchBgColor: '#E4E7EB',
    boxShadow: '0.8rem 0.8rem 1.5rem gray',
    categoryColor: '#999',
    categoryHoverColor: '#333',
})

The darkTheme function returns an object combining the common and dark properties from the imported themes variable.

Thus, the darkTheme function after evaluation looks like this:

const darkTheme = () => ({
    fontFamily:
        "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif",
    type: 'dark',
    bgColor: '#1F2933',
    color: '#E4E7EB',
    searchBgColor: '#E4E7EB',
    boxShadow: '0.4rem 0.4rem 1.5rem #111111',
    categoryColor: '#CBD2D9',
    categoryHoverColor: '#9AA5B1',
})

Later, in the App component, we use the useState React hook:

const App = () => {
  const [theme, setTheme] = useState(lightTheme())
  const setDarkTheme = () => setTheme(darkTheme())
  const setLightTheme = () => setTheme(lightTheme())
    return (
        <ThemeProvider theme={theme}>
            <>
                <Header>Hello React</Header>
                <button onClick={setLightTheme}>Make it light</button>
                <button onClick={setDarkTheme}>Make it dark</button>
            </>
        </ThemeProvider>
    )
}

useState takes in the default state, which we set to lightTheme(). If you set it to darkTheme(), then by default the dark theme will be displayed. useState returns two variables, which we named theme and setTheme. You can name them anything.

theme contains the current state — that is, lightTheme() — and setTheme is a function used to set a new state.

Then we have the setDarktheme function, which sets a dark them by calling setTheme and passing it the object returned by the function darkTheme(). The setLightTheme function works in a similar way.

Finally, we have two additional buttons to change themes — one to change it to light and other to dark.

But for this to work, we need to change our Header component using themes. So change it to the following:

const Header = styled.h1`
    background-color: ${props => props.theme.bgColor};
    color: ${props => props.theme.color};
`

Now the light theme looks like this:

Selected Light Theme

If you try clicking on the Dark Theme button, it will show the dark theme as follows:

Selected Dark Theme

Styled Components has a feature which lets you change your component styles dynamically using a prop. The background-color variable uses the prop theme.bgColor, while color uses the prop theme.color.

The theme variable mentioned here comes from ThemeProvider. The prop provided to ThemeProvider should be named theme. Otherwise it won’t work.

Now try clicking on the buttons to see themes changing.

The themes change, but it’s confusing which button to click. Let’s add a conditional that shows the light theme button only when the dark theme is shown, and vice versa.

Change the buttons in App.js as follows:

{theme.type === 'dark' && <button onClick={setLightTheme}>Make it light</button>}
{theme.type === 'light' && <button onClick={setDarkTheme}>Make it dark</button>}

This conditional makes sure to only show the relevant button depending on the theme selected.

Only shows light button on dark theme:

Show Light Button on Dark Theme

Only shows dark button on light theme:

Show Dark Button on Light Theme

Go ahead and download the assets/ folder and paste it into the src/ directory.

This will ensure we have all the images and icons we need in this project.

Now let’s change the buttons to icons. We’ll make the light button as a sun icon and dark button as a moon icon.

Import the icons into App.js:

import { ReactComponent as MoonSVG } from './assets/logos/moon.svg'
import { ReactComponent as SunSVG } from './assets/logos/sun.svg'

Then style those icons by extending the SVG. The following adds styles to the svg tag:

const SunIcon = styled(SunSVG)`
  width: 2rem;
  height: 2rem;
  margin-left: auto;
  cursor: pointer;
`

const MoonIcon = styled(MoonSVG)`
  width: 2rem;
  height: 2rem;
  margin-left: auto;
  cursor: pointer;
`

Notice how we’re duplicating the code above in both SunIcon and MoonIcon. Styled Components supports reusing styles.

Reusable CSS in Styled Components

Styled Components lets us reuse styles using a special helper function named css. Go ahead and import it from styled-components as follows:

import styled, { css, ThemeProvider } from 'styled-components'

Now you can reuse styles using the css prop as follows:

const ThemeIcon = css`
  width: 2rem;
  height: 2rem;
  margin-left: auto;
  cursor: pointer;
`

const MoonIcon = styled(MoonSVG)`
  ${ThemeIcon}
`

const SunIcon = styled(SunSVG)`
  ${ThemeIcon}
`

Finally, change the buttons to the following:

{theme.type === 'light' && <MoonIcon onClick={setDarkTheme} />}
{theme.type === 'dark' && <SunIcon onClick={setLightTheme} />}

The App.js file should now like this:

import React, { useState } from 'react'
import styled, { css, ThemeProvider } from 'styled-components'
import { ReactComponent as MoonSVG } from './assets/logos/moon.svg'
import { ReactComponent as SunSVG } from './assets/logos/sun.svg'
import { themes } from './utils/themes'

const lightTheme = () => ({
  ...themes['common'],
  ...themes['light'],
})

const darkTheme = () => ({
  ...themes['common'],
  ...themes['dark'],
})

const ThemeIcon = css`
  width: 2rem;
  height: 2rem;
  margin-left: auto;
  cursor: pointer;
`

const MoonIcon = styled(MoonSVG)`
  ${ThemeIcon}
`

const SunIcon = styled(SunSVG)`
  ${ThemeIcon}
`

const App = () => {
    const [theme, setTheme] = useState(lightTheme())
  const setDarkTheme = () => setTheme(darkTheme())
  const setLightTheme = () => setTheme(lightTheme())
    return (
        <ThemeProvider theme={theme}>
            <>
                <Header>Hello React</Header>
                {theme.type === 'light' && <MoonIcon onClick={setDarkTheme} />}
                {theme.type === 'dark' && <SunIcon onClick={setLightTheme} />}
            </>
        </ThemeProvider>
    )
}

export default App

And the site should now look like the following. It only shows the moon icon on the light theme:

Show Moon Icon on Light Theme

And it only shows the sun icon on the dark theme:

Show Sun Icon on Dark Theme

Global Styles in Styled Components

Now go ahead and create a components/ folder in src/ directory. Create a file named Global.js inside the components/ folder. Paste the following in it:

import { createGlobalStyle } from 'styled-components'

export const GlobalStyle = createGlobalStyle`
    *, *::before, *::after {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
    }

    html, body {
        height: 100vh;
        max-width: 100%;
        font-size: 62.5%;
        background-color: ${props => props.theme.bgColor};
        color: ${props => props.theme.color};
        font-family: ${props => props.theme.fontFamily};
    }
`

We have imported createGlobalStyle from styled-components. This lets us create global styles. And we later export the GlobalStyle variable as a named export. Notice how we’re using themes in our GlobalStyle. To make sure theming works, we need to make GlobalStyle a child of ThemeProvider. Otherwise it won’t work.

Go ahead and import Global.js in App.js and use it as follows:

import { GlobalStyle } from './components/Global'

.
.
.

const App = () => {
    .
    .
    .
    return (
        <ThemeProvider theme={theme}>
            <>
                <GlobalStyle />
                <Header>Hello React</Header>
                {theme.type === 'light' && <MoonIcon onClick={setDarkTheme} />}
                {theme.type === 'dark' && <SunIcon onClick={setLightTheme} />}
            </>
        </ThemeProvider>
    )
}

.
.
.

Global styles should be applied to our web app.

Global styles applied on the light theme:

Global Styles on Light Theme

Global styles applied on the dark theme:

Global Styles on Dark Theme

Now that we know the basics, let’s create the navbar for our Unsplash Redesign. Firstly, go ahead and remove the Header styled component from App.js.

Then go ahead and add the following in the App.js file:

import { ReactComponent as SearchSVG } from './assets/logos/search.svg'
import { ReactComponent as UnsplashLogoSVG } from './assets/logos/unsplash-logo.svg'
.
.
.

const Nav = styled.nav`
  display: flex;
  align-items: center;
  background-color: ${props => props.theme.bgColor};
  box-sizing: border-box;
  height: 8.2rem;
  padding-left: 2rem;
  padding-right: 2rem;
  position: fixed;
  width: 100%;
  z-index: 2;
`

const UnsplashLogo = styled(UnsplashLogoSVG)`
  fill: ${props => props.theme.color};
  width: 4rem;
  height: 4rem;
  backface-visibility: hidden;
  box-sizing: border-box;
  overflow: hidden;
  vertical-align: middle;
`

const TitleWrapper = styled.div`
  display: flex;
  flex-direction: column;
  margin-left: 1rem;
`

const Title = styled.h1`
  display: inline-block;
  font-size: 2rem;
  font-weight: 700;
  color: ${props => props.theme.color};
`

const Subtitle = styled.span`
  font-size: 1.3rem;
  font-weight: 500;
`

const SearchWrapper = styled.div`
  display: flex;
  align-items: center;
  background: ${props => props.theme.searchBgColor};
  border-radius: 3rem;
  border: 0.05rem solid #cbd2d9;
  margin-left: 7rem;
  box-shadow: none;
  :hover {
    border: 0.12rem solid #cbd2d9;
  }
`

const SearchIcon = styled(SearchSVG)`
  fill: #9aa5b1;
  width: 1.6rem;
  height: 1.6rem;
  margin-left: 1.2rem;
  margin-right: 1rem;
`

const SearchBar = styled.input`
  outline: none;
  border: none;
  width: 50rem;
  padding: 1rem 0;
  color: ${props => props.theme.categoryHoverColor};
  background: transparent;
  font-size: 1.4rem;
  font-weight: 300;
`

const App = () => {
  ..
  ..
  ..
  return (
    <ThemeProvider theme={theme}>
      <>
        <GlobalStyle />
        <Nav>
          <UnsplashLogo />
          <TitleWrapper>
            <Title>Unsplash</Title>
            <Subtitle>Photos for Everyone</Subtitle>
          </TitleWrapper>
          <SearchWrapper>
            <SearchIcon />
            <SearchBar placeholder="Search free high-resolution photos" />
          </SearchWrapper>
          {theme.type === 'light' && <MoonIcon onClick={setDarkTheme} />}
          {theme.type === 'dark' && <SunIcon onClick={setLightTheme} />}
        </Nav>
      </>
    </ThemeProvider>
  )
}

..
..
..

Notice that the only thing we’ve done differently is to add a :hover pseudo class on the SearchWrapper component. If you’ve come from Sass or SCSS, then Styled Components is pretty similar. You can even add child selectors inside a Styled Component just like Sass.

The nav should be properly displayed now.

The navbar on the light theme:

Navbar on Light Theme

The navbar on the dark theme:

Navbar on Dark Theme

Let’s create a component for listing categories. Create a file categories.js in the utils/ folder and paste the following:

export const categories = [
  'Wallpapers',
  'Textures & Patterns',
  'Nature',
  'Current Events',
  'Architecture',
  'Business & Work',
  'Film',
  'Animals',
  'Travel',
  'Fashion',
  'Food & Drink',
  'Spirituality',
  'Experimental',
  'People',
  'Health',
  'Arts & Culture',
]

Also, create a component named CategoriesList.js in the components/ folder.

Paste the following code into it:

import React from 'react'
import styled from 'styled-components'
import { categories } from '../utils/categories'

const Categories = styled.div`
  padding-bottom: 2rem;
  padding-left: 2rem;
  position: fixed;
  margin-top: 8.2rem;
  top: 0;
  bottom: 0;
  overflow-y: scroll;
  width: 23rem;
  background: ${props => props.theme.bgColor};
  z-index: 2;
`

const CategoryName = styled.a`
  background-color: transparent;
  cursor: pointer;
  box-sizing: border-box;
  color: ${props => props.theme.categoryColor};
  display: block;
  font-size: 1.4rem;
  font-weight: 500;
  line-height: 1;
  padding-bottom: 1.7rem;
  padding-top: 2.1rem;
  text-decoration: none;
  white-space: nowrap;
  :hover {
    color: ${props => props.theme.categoryHoverColor};
    outline: none;
  }
`

const Category = ({ name }) => <CategoryName href="#">{name}</CategoryName>

export const CategoriesList = () => (
  <Categories>
    {categories.map((category, i) => (
      <Category name={category} key={i} i={i} />
    ))}
  </Categories>
)

Now go ahead and import it in App.js and paste it just below the Nav component:

import { CategoriesList } from './components/CategoriesList'
..
..
..

const App = () => {
  ..
  ..
  ..
  return (
    <ThemeProvider theme={theme}>
      <>
        <Nav>
          ..
          ..
          ..
        </Nav>
        <CategoriesList />
        ..
        ..
        ..
      </>
    </ThemeProvider>
  )
}

..
..
..

Now a list of categories will be shown in the sidebar.

The list of categories on the light theme:

Categories List on Light Theme

The list of categories on the dark theme:

Categories List on Dark Theme

Let’s create our final component that displays pics. Create a file named pics.js in the utils/ folder. Paste the following into it:

export const pics = [
  require('../assets/pics/asset 0.jpeg'),
  require('../assets/pics/asset 1.jpeg'),
  require('../assets/pics/asset 2.jpeg'),
  require('../assets/pics/asset 3.jpeg'),
  require('../assets/pics/asset 4.jpeg'),
  require('../assets/pics/asset 5.jpeg'),
  require('../assets/pics/asset 6.jpeg'),
  require('../assets/pics/asset 7.jpeg'),
  require('../assets/pics/asset 8.jpeg'),
  require('../assets/pics/asset 9.jpeg'),
  require('../assets/pics/asset 10.jpeg'),
  require('../assets/pics/asset 11.jpeg'),
  require('../assets/pics/asset 12.jpeg'),
  require('../assets/pics/asset 13.jpeg'),
  require('../assets/pics/asset 14.jpeg'),
  require('../assets/pics/asset 15.jpeg'),
  require('../assets/pics/asset 16.jpeg'),
  require('../assets/pics/asset 17.jpeg'),
  require('../assets/pics/asset 18.jpeg'),
  require('../assets/pics/asset 19.jpeg'),
  require('../assets/pics/asset 20.jpeg'),
  require('../assets/pics/asset 21.jpeg'),
  require('../assets/pics/asset 22.jpeg'),
  require('../assets/pics/asset 23.jpeg'),
  require('../assets/pics/asset 24.jpeg'),
  require('../assets/pics/asset 25.jpeg'),
  require('../assets/pics/asset 26.jpeg'),
  require('../assets/pics/asset 27.jpeg'),
  require('../assets/pics/asset 28.jpeg'),
  require('../assets/pics/asset 29.jpeg'),
  require('../assets/pics/asset 30.jpeg'),
  require('../assets/pics/asset 31.jpeg'),
  require('../assets/pics/asset 32.jpeg'),
  require('../assets/pics/asset 33.jpeg'),
  require('../assets/pics/asset 34.jpeg'),
  require('../assets/pics/asset 35.jpeg'),
  require('../assets/pics/asset 36.jpeg'),
  require('../assets/pics/asset 37.jpeg'),
  require('../assets/pics/asset 38.jpeg'),
  require('../assets/pics/asset 39.jpeg'),
  require('../assets/pics/asset 40.jpeg'),
  require('../assets/pics/asset 41.jpeg'),
  require('../assets/pics/asset 42.jpeg'),
  require('../assets/pics/asset 43.jpeg'),
  require('../assets/pics/asset 44.jpeg'),
  require('../assets/pics/asset 45.jpeg'),
  require('../assets/pics/asset 46.jpeg'),
  require('../assets/pics/asset 47.jpeg'),
  require('../assets/pics/asset 48.jpeg'),
  require('../assets/pics/asset 49.jpeg'),
  require('../assets/pics/asset 50.jpeg'),
  require('../assets/pics/asset 51.jpeg'),
  require('../assets/pics/asset 52.jpeg'),
  require('../assets/pics/asset 53.jpeg'),
]

Also create a Pic.js file in components/ folder and paste the following:

import React from 'react'
import ImageZoom from 'react-medium-image-zoom'
import styled from 'styled-components'

const ImageWrapper = styled.div`
  margin: 0.5rem;
  transition: all 200ms ease;
  :hover {
    box-shadow: ${props => props.theme.boxShadow};
    transform: scale(1.005);
  }
`

export const Pic = ({ src, i }) => {
  const alt = `Unsplash Redesign #${i}`
  const imageProps = { src, alt }
  return (
    <ImageWrapper>
      <ImageZoom
        image={imageProps}
        zoomImage={imageProps}
        defaultStyles={{
          image: { width: '37rem', height: '48rem' },
        }}
      />
    </ImageWrapper>
  )
}

We’re using react-medium-image-zoom, which lets you zoom in on an image like Medium.

Now go ahead and import Pic.js in App.js and paste it just below the CategoriesList component. Also, add Grid and GridWrapper styled components as follows:

import { Pic } from './components/Pic'
import { pics } from './utils/pics'

..
..
..

const GridWrapper = styled.div`
  display: flex;
  justify-content: center;
`

const Grid = styled.div`
  padding-top: 8.2rem;
  padding-left: 23rem;
  display: grid;
  grid-template-columns: repeat(3, 38rem);
  margin-bottom: 1.5rem;
`

const App = () => {
  ..
  ..
  ..
  return (
    <ThemeProvider theme={theme}>
      <>
        ..
        ..
        ..
        <CategoriesList />
        <GridWrapper>
          <Grid>
            {pics.map((pic, i) => (
              <Pic src={pic} key={i} i={i} />
            ))}
          </Grid>
        </GridWrapper>
      </>
    </ThemeProvider>
  )
}

..
..
..

Now a grid with pics should appear.

The Unsplash redesign with the light theme:

Unsplash Redesign - Light Theme

The Unsplash redesign with the dark theme:

Unsplash Redesign - Dark Theme

We just redesigned Unsplash using styled-components. Try zooming in on the image to see it working. You can check the live demo here.

Conclusion

Styled Components makes it easy to write plain ol’ CSS in your JS. It allows us to colocate styles with our components so that we can add styles, edit them or remove them easily.

We learned how to add Global Styles, reuse styles using a css prop and how to theme an application. We’ve only scratched the surface with styled-components; it has a lot more to offer. You can learn more about it on the official website.

We finally redesigned Unsplash using Styled Components. The complete code is available on GitHub and the demo is available here.