/ nodejs

Beautiful Web Design With Semantic UI 2.2 and NodeJS Server-side Rendering

It's worth pointing out that Semantic UI provides richer UI elements and robust features than Bootstrap 3/4. Semantic UI does contain more elements without the needs of 3rd party libraries. For examples:

  • dropdown has built-in animation & search function.
  • Step, Rating, Statistic are not exist in Bootstrap 3/4.
  • Semantic UI comes with more than 20 themes.
  • The CSS class names are more friendly to human words.

(Semantic UI is available for download if you haven't tried it yet, and want to.)

This is a steps by steps guild show you how to create a basic Semantic UI theme, customize it, and setup the NodeJS server-side rendering development environment.

Prerequisite

This project leverages below technologies:

Install NodeJS

You can download & install the NodeJS from official site or using NVM to install NodeJS. Moreover, NVM offers switching different NodeJS version anytime. I'm using the version of NodeJS & NPM is:

node -v && npm -v
v8.9.0
5.5.1

Project Setup

Create the server App

Create a new directory for our project and initialise it using NPM. Type below commands in Terminal:

mkdir [your_project_name] && cs [your_project_name]
npm init -y
mkdir public
mkdir public/js
mkdir public/css
mkdir public/images
mkdir views

Specify server startup file

Modify the below properties inside the package.json file:

...
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
...

Install the ExpressJS

ExpressJS is a lightweight framework for NodeJS. To install it, type below command in project root directory:

npm install --save express

Install the Task runner

Gulp is a task runner for build processes. It is similar to batch file but provides much more powerful features. In project root directory, run below commands to install Gulp & its helpers:

npm install -g gulp-cli
npm install --save-dev gulp gulp-chug gulp-csso gulp-less gulp-pug run-sequence

Install Semantic UI

To install Semantic UI into our project, type below command in project root:

npm install semantic-ui --save

After answer few questions from Semantic UI with default values, then build the Semantic UI:

cd semantic
gulp build
cd ..

After the semantic-ui build, the built files are stored in ./dist/. That's mean initial setup is done. Let's get started for site customization.

Create the home page

I've translated a PUG (HTML template engine) file views/index.pug. This is the home page of this project. The PUG file contain almost everything of Semantic Ui elements in PUG syntax. For example:

.ui.container
    h1 Theming Examples

    h2.ui.dividing.header Site
    .ui.three.column.stackable.grid
        .column
            h1 Heading 1
            h2 Heading 2
            ...
 .ui.three.column.stackable.padded.middle.aligned.centered.color.grid
                .column.red Red
                .column.orange Orange
                .column.yellow Yellow
                ...

As you can see, PUG syntax is not only the shorthand of HTML. But also type fewer and cleaner. Furthermore, it is more human words like.

You can see the full file of views/index.pug at here.

Although we can view the PUG file using PUG view engine provided by ExpressJS, I chose pre-rendered approach in this project. It is mentioned in below Gulp build processes.

Create the server program

In project root directory, create a simple NodeJS server program app.js:

const express = require('express')
const app = express()

app.use(express.static('public'))

app.listen(3000, () => console.log('The app listening on port 3000!'))

Create Gulp task file

In project root directory, create a file gulpfile.js. The content is:

const gulp = require('gulp')
const pug = require('gulp-pug')
const less = require('gulp-less')
const minifyCSS = require('gulp-csso')
const runSequence = require('run-sequence')
const chug = require('gulp-chug')

const OUTPUT_DIR = 'public'

gulp.task('html', () => {
  return gulp.src('views/*.pug')
    .pipe(pug())
    .pipe(gulp.dest(OUTPUT_DIR))
})

gulp.task('css', () => {
  return gulp.src('views/stylesheets/*.less')
    .pipe(less())
    .pipe(minifyCSS())
    .pipe(gulp.dest(OUTPUT_DIR + '/css'))
})

gulp.task('images', () => {
  return gulp.src('views/images/**/*')
    .pipe(gulp.dest(OUTPUT_DIR + '/images'))
})

gulp.task('js', () => {
  return gulp.src('views/javascripts/*.js')
    .pipe(gulp.dest(OUTPUT_DIR + '/js'))
})

// Run another Gulp build to build Semantic UI
gulp.task('build-semantic', () => {
	return gulp.src('./semantic/gulpfile.js')
		.pipe(chug({ tasks: ['build'] })) // Run 'gulp build' in /semantic
})

// Copy built Semantic UI files to /public
gulp.task('copy-semantic', () => {
  return gulp.src('semantic/dist/semantic.min.css')
    .pipe(gulp.dest(OUTPUT_DIR + '/css'))
  gulp.src('semantic/dist/semantic.min.js')
    .pipe(gulp.dest(OUTPUT_DIR + '/js'))
  gulp.src('semantic/src/themes/default/assets/fonts/**/*')
    .pipe(gulp.dest(OUTPUT_DIR + '/css/themes/default/assets/fonts'))
  gulp.src('semantic/src/themes/default/assets/images/**/*')
    .pipe(gulp.dest(OUTPUT_DIR + '/css/themes/default/assets/images'))
})

// Semantic UI requires jQuery
gulp.task('copy-jquery', () => {
	gulp.src('node_modules/jquery/dist/jquery.min.js')
		.pipe(gulp.dest(OUTPUT_DIR + '/js'))
})

// Gulp default task.
gulp.task('default', () => {
	runSequence(
		['html', 'css', 'js', 'images', 'copy-jquery'],
		'build-semantic',
		'copy-semantic'
	)
})

Now build our project. In project root, type:

gulp

After about 30 sec in my computer, the built files are generated in directory /public. Lets run the server:

npm start

Open the browser and browse http://localhost:3000. The home page should looks like:
scrcap_001

You'll see many Semantic UI elements in there. That is the default theme of Semantic UI. But you'll noticed that no action when clicking the some elements e.g. menu, dropdowns, etc. We need to create Javascript codes to initialise the Semantic UI. See following sction.

Create our own stylesheet and javascript

Semantic UI requires jQuery to initialise some elements. So I created a views/javascripts/demo.js javascript:

$(document).ready(function() {
	$('.ui.menu .ui.dropdown').dropdown({
		on: 'hover'
	})
	$('.ui.menu a.item').on('click', function() {
		$(this).addClass('active').siblings().removeClass('active')
	})

	$('.ui.dropdown').dropdown();
	$('.ui.buttons .dropdown.button').dropdown({
		action: 'combo'
	})

	// add popup to show name
	$('.ui:not(.container, .grid)').each(function() {
		$(this).popup({
			on        : 'hover',
			variation : 'small inverted',
			exclusive : true,
			content   : $(this).attr('class')
		})
	})

	$('.ui.dropdown').dropdown({
		on: 'click'
	})

	$('.special.card .image').dimmer({
		on: 'hover'
	})
	$('.star.rating').rating()
	$('.card .dimmer').dimmer({
		on: 'hover'
	})
})

In addition, we need to add some extra styles for this demo. Create a stylesheet in views/stylesheets/demo.less as below content:

body {
	padding: 1em;
}
.spaced > .button {
	margin-bottom: 1em;
}
.color.grid {
	margin: -1.5em;
	width: 400px;
}
.ui.table {
	table-layout: fixed;
}
.color.grid .column {
	margin: 0.5em;
	width: 50px;
	height: 50px;
}
.ui.menu {
	margin: 3em 0em;
}
.ui.menu:last-child {
	margin-bottom: 110px;
}
.ui.table {
	table-layout: fixed;
}
.ui.input + .ui.input {
	margin-left: 1em;
}

Note that the above LESS file is used by this project only.

Create our own theme for Semantic UI using LESS

Semantic UI default theme is stored in semantic/src/themes/default directory. Now we create our own theme directory, e.g. mytheme. And copy all files from default to mytheme recursively. In project root, type:

mkdir semantic/src/themes/mytheme
cp -R semantic/src/themes/default/* semantic/src/themes/mytheme/

Next step is to tell Semantic UI to use & build the new theme. Edit /semantic/src/theme.config file Global section, replace all 'default' values to 'mytheme':

...
/* Global */
@site       : 'mytheme';
@reset      : 'mytheme';

/* Elements */
@button     : 'mytheme';
@container  : 'mytheme';
...

Adjust the font size bigger little bit. Edit the Semantic UI site file semantic/src/themes/mytheme/globals/site.variables Base Sizes section, as below:

/*-------------------
      Base Sizes
--------------------*/

/* This is the single variable that controls them all */
@emSize   : 18px; // Original 14px

/* The size of page text  */
@fontSize : 18px; // Original 14px

Next step is to change the color. Every website has its own brand color. We can create and assign our own brand color into the Semantic UI. To create brand color, we can use COOLORS. Coolors does has very nice interface. And it is very easy to create our own color scheme. Below is the screenshot when I create my brand color scheme:
scrcap_002

When finish, copy & paste the colors into the Semantic UI site file (same file as above) semantic/src/themes/mytheme/globals/site.variables Brand Colors section, as below:

...
/*-------------------
    Brand Colors
--------------------*/

@primaryColor        : #5D7EA1;
@secondaryColor      : #8FB2B1;

@lightPrimaryColor   : #77A6B6;
@lightSecondaryColor : #B3D89C;
...
...
/*-------------------
        Page
--------------------*/

@pageBackground      : #F2FAE9;
...

At this time, we can run build processes again. Type gulp again and refresh the browser. The home page is changed to:
scrcap_001-1

Conclusion

We've created a new basic Semantic UI theme. You can add more pages for your project. I would suggest that to configure the Gulp to watch the LESS files instead of rebuild the whole Semantic UI everytime.

All source codes of this project are stored in this Github repo.