Semantic UI is a great UI framework which can make your UI development much easier, but it’s still not a joyful job to make it work with webpack especially for theming.
This tutorial works for both webpack 1/2/3, though you need to make small change just to follow webpack2/3’s syntax. For the main differences for webpack2/3, scroll to the bottom!
Use Semantic-UI without theming
If you just want to use Semantic-UI with your Webpack-React project, it’s quite easy.
You only need to follow two steps:
npm install semantic-ui-react --save
(see semantic-ui-react)- Since the
semantic-ui-react
does not include style, you can use the default Semantic UI stylesheet by including a Semantic UI CDN link in your index.html file.
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.2/semantic.min.css"></link>
Just create a simple button in your code to test if it is working:
import React from 'react';
import { Button } from 'semantic-ui-react';
const ButtonExampleButton = () => (
<Button>
Click Here
</Button>
)
export default ButtonExampleButton
Instead of using a Semantic UI CDN link, you can manually handle the CSS by yourself, just:
npm install semantic-ui-CSS --save
- In your entry file, include the entry file:
// app.js
import 'semantic-less-css/semantic.css';
Remember to turn off the “CSS-Module” functionality for .css
file. And notice that both using CDN or semantic-ui-css
do not provide the theming feature.
Theming
To be able to use the theming feature, you need to use semantic-ui-less. It’s a pure less part of Semantic UI aiming to help you get rid of all the unnecessary dependencies from Semantic-UI.
npm install semantic-ui-less --save
And since it’s Less, and there are also Icon Fonts involved in this module, make sure your webpack can handle them well:
// webpack configs:
.....
loaders: [
{
test: /\.less/,
loader: 'style!css!less',
},
{
test: /\.(png|jpg|gif|woff|svg|eot|ttf|woff2)$/,
loader: 'url-loader?limit=1024&name=[name]-[hash:8].[ext]!image-webpack',
},
],
...
Before we start the work, let’s take a look at the project structure (you can check out the demo project):
app/
-- index.js
-- index.html
-- semantic-ui/ // all the semantic-ui related files
----- site/ // theming related files
webpack.config.js
package.json
rewrite less import for ../../theme.config
semantic-ui-less
tries to import a file that does not exist( node_modules/semantic-ui-less/theme.config
), this file includes some key variables used throughout the whole module.
So first of all, you need to create a theme.config
by yourself ( create a directory named semantic-ui
in your project root):
app/semantic-ui
- theme.config
And copy the content of node_modules/semantic-ui-less/theme.config.example
into theme.config
and remember to do a import path fix, change @import "theme.less"
to @import "~semantic-ui-less/theme.less"
:
Also don’t forget to change the @siteFolder
to your folder:
@siteFolder : '../../app/semantic-ui/site';
After that, we can use a Less plugin to make the ../../theme.config
refer to our own theme.config
. Let’s intall the module first:
npm install less-plugin-rewrite-import --save-dev
Then add the configuration to webpack.config.js
:
const RewriteImportPlugin = require("less-plugin-rewrite-import");
... below is just part of the webpack config
essLoader: {
lessPlugins: [
new RewriteImportPlugin({
paths: {
'../../theme.config': __dirname + '/app/semantic-ui/theme.config',
},
}),
],
},
...
You can now import the main entry of semantic-ui-less
from /app/index.js
:
import "semantic-ui-less/semantic.less";
Anyway, you will still get build error complaining about that it can’t find font files.
Fix @fontPath error
What you need to do is just add one line of code showed bellow at the bottom of your theme.config
( make sure it’s bellow the line that imports theme.less
):
@fontPath : '../../../themes/@{theme}/assets/fonts';
Now the build process should work like a charm.
Setup customization for your site
Create extra structure for your semantic-ui directory:
/semantic-ui
- theme.config
- site/
Most of custom style code goes into site/
folder, the structure will be like this:
site/
- collections/
- elements/
- globals/
- modules/
- views/
To verify whether the customisation is working, just create /app/semantic-ui/site/elements/button.variables
and change background color for all buttons:
@backgroundColor: yellow;
Put a button into your page /app/index.ejs
to see if it works:
<div class="ui button">Button</div>

If you see the same, it works.
Theming for Webpack2 / 3
For those working with Webpack2 or 3, except for general syntax change, there’re two differences you need to make for the theming to work. (Thanks for @MarkPerryBV’s idea from this issue)
Use less-resolver
By default, less-loader
will use webpack’s resolver to resolve all the less files, making plugins like less-plugin-rewrite-import
fail to handle less files. That’s why you will find the plugin not working for webpack2.
To make less-loader
use its own resolver, you need to manually specify option paths
for it to search, your config should be:
{
loader: 'less-loader',
options: {
paths: [ROOT_DIR, NODE_MODULES_DIR], // this will force less-loader to use its own resolver, both should be absolute path
plugins: [
new RewriteImportPlugin({
paths: {
'../../theme.config': __dirname + '/app/semantic-ui/theme.config',
},
}),
],
},
},
You can get more details about less resolver from here
Remove ~
in your theme.config
Since now we are using less resolver, we are not able to use ~
to refer modules in the node_modules
anymore, so open your theme.config
and change the @import "~semantic-ui-less/theme.less";
to @import "semantic-ui-less/theme.less";
For more specific example, checkout my example project: demo-semantic-ui-theming-with-webpack2
22 Comments
Could you post an example repo? I can’t seem to get this working.
Hi @Vin, I have updated the post, and you can find the working demo here: https://github.com/neekey/demo-semantic-ui-theming-with-webpack
Everything works great. But on last step, I dont see any effects. I checked and my site folder is not getting executed.
Fixed it.
In theme.config, I changed path of my site folder to (its relative from the module)
@siteFolder : ‘../../semantic-ui/site’;
Hi @Nix, thanks for pointing this out, I have updated the post : )
Can’t seem to get this working with webpack 2. Can you help?
Hey @neekey, I don’t suppose you have this working with Webpack 2? I have tried but for the life of me haven’t been able to get the rewrite import plugin working.
Even if I added the reweriteImportPlugin, I still have the same error!
ERROR in ./~/css-loader!./~/less-loader/lib/loader.js!./~/semantic-ui-less/semantic.less
Module build failed: Cannot resolve ‘file’ or ‘directory’ ../../theme.config in /Users/jharvey/Serdy/www/fe-refonte/fe-client/node_modules/semantic-ui-less/definitions/modules
@ /Users/jharvey/Serdy/www/fe-refonte/fe-client/node_modules/semantic-ui-less/definitions/modules/transition.less (line 19, column 0)
near lines:
@import (multiple) ‘../../theme.config’;
@ ./~/semantic-ui-less/semantic.less 4:14-94 13:2-17:4 14:20-100
Does anyone try to do this with Webpack 2?
Sorry for late reply, the configuration in this POST does not work for Webpack2, the I was working on it, but the main issue is that I couldn’t make the `RewriteImportPlugin` work even with the latest version, you can experiment with my demo project [here](https://github.com/neekey/demo-semantic-ui-theming-with-webpack2), may spend more time later on
Hi John, not sure if you have solved this issue already, just want you to know that I have found a solution and have updated the article. You can check out the project as well.
Wow! Helped me lot to get this working. Thank you very much for this post.
One little note: The `RewriteImportPlugin` does not work with less-loader >= 4.0.0. Downgraded for now to 2.2.3 to get it working.
Thanks for pointing out, apparently less-loader >= 4 is meant for Webpack2
Does not work anymore with webpack 2.
Sorry for late reply, the configuration in this POST does not work for Webpack2, the I was working on it, but the main issue is that I couldn’t make the `RewriteImportPlugin` work even with the latest version, you can experiment with my demo project [here](https://github.com/neekey/demo-semantic-ui-theming-with-webpack2), may spend more time later on
Hi Alban, not sure if you have solved this issue already, just want you to know that I have found a solution and have updated the article. You can check out the project as well.
Any ideas on how to get RewriteImportPlugin working with webpack2?
I’m trying with the loaderOptionsPlugin, but i’m getting something seriously wrong
https://github.com/jimmyjamieson/rrtest/blob/master/webpack.config.js
Sorry for late reply, the configuration in this POST does not work for Webpack2, the I was working on it, but the main issue is that I couldn’t make the `RewriteImportPlugin` work even with the latest version, you can experiment with my demo project [here](https://github.com/neekey/demo-semantic-ui-theming-with-webpack2), may spend more time later on
Ok, i fixed it by skipping that plugin and just using a postinstall in my package.json of
“postinstall”: “node font-fix.js && cp ./src/app/styles/semantic-ui/theme.config ./node_modules/semantic-ui-less/theme.config”
Yes, Ian, you can always do that, but the reason I wrote this post was that I wanted to get a more elegant way to achieve this, but as soon as it works for you, it’s good : )
Hi Ian, not sure if you have solved this issue already, just want you to know that I have found a solution and have updated the article. You can check out the project as well.
Can’t seem to find a workaround for ejected CRA project with webpack 4