DEV Community

Kudakwashe Gore
Kudakwashe Gore

Posted on

How to customize Semantic UI with React, MiniCssExtractPlugin, LESS and Webpack 4?

Introduction

This tutorial assumes that you already know how to set up a basic react app and webpack.

Setting up Semantic UI and extending/overriding the default themes with your custom styles in a React app can give you a bad day if not done carefully.

On the webpack side, after ExtractTextPlugin was deprecated and replaced with MiniCssExtractPlugin, configuring your webpack to recognise your Semantic UI less and fonts can also be a pain if you haven't done that before.

This tutorial can help you get started within a few minutes, it can also work with Fomantic UI Less.

Code for this tutorial can be found on https://github.com/kudakwashegore/custom-semanticui-react

Dependencies

First things first, a basic setup will require installation of the following dependencies (I use npm, yarn can also work).

npm i -D mini-css-extract-plugin semantic-ui-less less@2.7.3 less-loader css-loader url-loader

npm i -S semantic-ui-react

Please note the version of less used (2.7.3). Later versions will give you endless nightmares.

I also deliberately used url-loader instead of file-loader, file-loader will give you issues when you want to use your favourite Semantic UI <Icon />.

Folder Structure

Assuming the following project structure, you can always update your code to match your folder structure.

node_modules/
app/
  app.js
  index.html
my-custom-semantic-theme/
webpack.config.js
package.json

Webpack

Below are some additional webpack configuration that you need to add in your webpack configuration file.

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');

module.exports = {
    resolve: {
      alias: {
        '../../theme.config$': path.join(
          __dirname,
          '../my-custom-semantic-theme/theme.config',
        ),
      },
    },
    module: {
      rules: [
        {
          test: /\.less$/,
          use: [
            {
              loader: MiniCssExtractPlugin.loader,
            },
            'css-loader',
            'less-loader',
          ],
        },
        {
          test: /\.woff($|\?)|\.woff2($|\?)|\.ttf($|\?)|\.eot($|\?)|\.svg($|\?)/,
          use: 'url-loader',
        }
      ],
    },
    plugins: [
      new MiniCssExtractPlugin({
        filename: 'styles/[name].[contenthash].css',
      }),
    ],
  };

Semantic UI

  • Go on https://github.com/Semantic-Org/Semantic-UI-LESS and download the repo into your my-custom-semantic-theme/ folder.
  • Rename file theme.config.example to theme.config.
  • Rename _site folder to site
  • Delete other folders and files in your my-custom-semantic-theme/ folder and remain with
  my-custom-semantic-theme/
      site/
      theme.config
      theme.less
  • Open theme.config and have the last lines match the following
   /*******************************
            Folders
   *******************************/

   /* Path to theme packages */
   @themesFolder : 'themes';

   /* Path to site override folder */
   @siteFolder  : '../../my-custom-semantic-theme/site';


   /*******************************
         Import Theme
   *******************************/

   @import (multiple) "~semantic-ui-less/theme.less";

   @fontPath : "../../../themes/@{theme}/assets/fonts";

   /* End Config */

App

We are almost ready. Below is an example of a basic app.js using semantic-ui-react components.

  import React from 'react';
  import ReactDOM from 'react-dom';
  import { Icon, Button, Segment, Label } from 'semantic-ui-react';
  import 'semantic-ui-less/semantic.less'; // if you do this once in your entry point file, you don't have to do it again in other files.

  ReactDOM.render(
  <Segment>
    <p>Hello semantic-ui button with icon</p>
    <Button as='div' labelPosition='right'>
      <Button color='red'>
        <Icon name='heart' />
        Like
      </Button>
      <Label as='a' basic color='red' pointing='left'>
        2,048
      </Label>
    </Button>
  </Segment>,
  document.getElementById('appRoot'),
);

Testing our app

We are now ready to test if semantic-ui-less is correctly setup. Do the npm start thing.

To check if you can now override the default semantic-ui styles with your own, open /my-custom-semantic-theme/site/elements/button.variables and add the following line

@backgroundColor: green;

Refresh your app and you should see your button background color changing to brown.

You can download example code on https://github.com/kudakwashegore/custom-semanticui-react

Latest comments (2)

Collapse
 
alexcourt profile image
AlexCourt

Thank you for this, and you're linked git project. If it helps anyone else I had to set the version of less-loader so it would play nicely:

npm i -D less-loader@5.0.0

Collapse
 
erich93063 profile image
erich93063

Will this same procedure work with Next.js?