Jun 21st, 2016 - written by Kimserey with .
Have you ever been guilty of referencing Bootstrap
in your web app just to use one feature (like the navbar for example)? Hunting for the most full featured CSS/JS UI framework for hours.
Referencing a huge framework just to use one or two features. Bootstrap
, Foundation
, MUI
or Materialize
, there are so many that it takes a lot of time to find the one that fits your needs.
Few months back, I started to build a prototype to manage expenses and all I needed was a navbar
and a card
style. Because of bad habits, I directly started to hunt for a UI framework which would provide me beautiful cards. After few hours of search, I realised how time consuming that was and most importantly how unlikely would it be for me to find something tailored for my needs.
So I decided to do something that I should have done long ago - Build my own tailored JS/CSS UI framework.
So today, I will share what I’ve learnt during the process of creating the JS/CSS UI framework. This post is composed by two parts:
1
2
1. Build your UI framework with JS and SCSS
2. Use Paket with GitHub dependency to keep your web app on the latest update of your UI framework
To write this UI framework, I used JS and SCSS (SASS). I won’t talk about the JS part as I used it purely to handle on click events and show/hide certain elements. I chose SCSS because it has a more natural way of defining CSS classes than directly writing in CSS.
The main benefits that SCSS or SASS gives me are the following:
You can declare variables. These variables can then be used anywhere and assigned to any style.
1
2
3
4
5
6
$grey: #808080;
...somewhere else...
color: $grey;
border-bottom: 1px solid $grey;
Here’s an example usage: https://github.com/Kimserey/SimpleUI/blob/master/scss/shared/_colors.scss
The creation of nested style is made more intuitive. The hiearchy of your classes is respected by the hierarchy defined by your HTML elements.
1
2
3
4
5
.card {
.card-list {
...
}
}
This will match the following HTML:
1
2
3
<div class="card">
<div class="card-list"></div>
</div>
&
can be used within a class to reference the parent. It is a clean way to define child classes.
1
2
3
4
5
.card {
&.active {
...
}
}
This will match the following HTML:
1
2
3
<div class="card">
<div class="card-list active"></div>
</div>
You can separate your style into multiple files.
@import
lets you import partial files prefixed with an underscore _
.
1
2
3
4
5
@import "components/amount";
@import "components/card";
@import "components/mask";
@import "components/nav";
@import "components/table";
Here’s an example usage: https://github.com/Kimserey/SimpleUI/blob/master/scss/SimpleUI.scss
You can create reusable functions which set some styles using @mixins
for the definition and @include
to include them in your classes.
1
2
3
4
5
6
7
8
9
10
11
@mixin transition($args...) {
-webkit-transition: $args;
-moz-transition: $args;
-ms-transition: $args;
-o-transition: $args;
transition: $args;
}
...somewhere else...
@include transition(0.2s);
Here’s an example usage: https://github.com/Kimserey/SimpleUI/blob/master/scss/mixins/_transition.scss
SCSS needs to be translated to CSS.
For that we can use gulp
- a JS task runner - to create a Visual Code task which will execute three functions:
dist
dist
First install gulp
from npm
by executing the following commands:
1
2
3
4
npm install --save-dev gulp
npm install --save-dev gulp-sass
npm install --save-dev gulp-minify-css
npm install --save-dev gulp-uglify
Then create a gulpfile.js
file in the root folder:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var gulp = require('gulp');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var uglify = require('gulp-uglify');
gulp.task('default', function() {
gulp.src('./scss/SimpleUI.scss')
.pipe(sass())
.pipe(gulp.dest("./css"));
gulp.src('./css/SimpleUI.css')
.pipe(minifyCss())
.pipe(gulp.dest('./dist/css'));
gulp.src('./js/SimpleUI.js')
.pipe(uglify())
.pipe(gulp.dest('./dist/js'))
});
The main function .task(...)
defines the task which will be run as default. Inside we execute the three functions describe earlier.
1
2
3
gulp.src('./scss/SimpleUI.scss')
.pipe(sass())
.pipe(gulp.dest("./css"));
This function instructs gulp
to take our main SCSS SimpleUI.scss
and compile the CSS using the sass
function.
Then outputs the result in the /css
folder.
1
2
3
gulp.src('./css/SimpleUI.css')
.pipe(minifyCss())
.pipe(gulp.dest('./dist/css'));
This functions instructs gulp
to take the SimpleUI.css
result and minifies it using the minifyCss
function and place the result in the dist
folder (short form for distribution).
Then the same process is done for the JS using the uglify
function with SimpleUI.js
.
Lastly what we need to do is create a .vscode
folder, create a tasks.json
file and add the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"version": "0.1.0",
"command": "gulp",
"isShellCommand": true,
"tasks": [
{
"taskName": "default",
"isBuildCommand": true,
"showOutput": "always",
"isWatching": true
}
]
}
Now CTRL
+ SHIFT
+ B
should launch the task and build the minified CSS and JS.
Also the task should be accessible from CTRL
+ SHIFT
+ P
, Run Tasks.
The full SimpleUI
source code can be found here: https://github.com/Kimserey/SimpleUI
Congratulation, you can now start to build your own JS/CSS framework!
Last week I talked about how WebSharper manages resources for SPA https://kimsereyblog.blogspot.co.uk/2016/06/three-ways-to-manage-your-resources-for.html. I mentioned that the JS and CSS can be bundled together with the web app JS - but in order to do that, you need to place your resources as embedded resources.
So how do I embed the JS and CSS created ealier into my web app?
The best way I found was to:
1
2
3
1. Push your code into a GitHub repository
2. Use Paket GitHub dependency to add a dependency on your UI framework
3. Embed the paket files into your WebSharper project
After you have pushed your git repo like mine https://github.com/Kimserey/SimpleUI, you can use Paket to add a dependency on a GitHub file.
If you haven’t heard of Paket before, I made a small tutorial on how to get started with Paket https://kimsereyblog.blogspot.co.uk/2016/01/quick-setup-with-paket-and-fsx-scripts.html.
To add a Paket GitHub file dependency, go to paket.dependencies
under your root folder and add the following lines:
1
2
github Kimserey/SimpleUI dist/css/SimpleUI.css
github Kimserey/SimpleUI dist/js/SimpleUI.js
Here’s an example: https://github.com/Kimserey/SimpleUIWeb/blob/master/paket.dependencies#L9
Then run the following command in your terminal:
1
.paket\paket.exe update
Excellent, you should now have your files added under a paket-files
folder and you can then add the two files as Embedded resource
in your WebSharper SPA project.
Finally, add the resources with the BaseResource
attribute and the Require
attribute like followed:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
namespace SimpleUIWeb
open WebSharper
open WebSharper.Resources
open WebSharper.JavaScript
module Resources =
type Fontawesome() =
inherit BaseResource("https://use.fontawesome.com/269e7d57ca.js")
type Css() =
inherit BaseResource("SimpleUI.css")
type Js() =
inherit BaseResource("SimpleUI.js")
[<assembly:Require(typeof<Fontawesome>);
assembly:Require(typeof<Css>);
assembly:Require(typeof<Js>)>]
do()
[<JavaScript>]
module Client =
open WebSharper.UI.Next
open WebSharper.UI.Next.Html
open WebSharper.UI.Next.Client
let Main =
Console.Log "Started"
Tutorial on how to manage resources with BaseResource
and Require attribute
can be found here: https://kimsereyblog.blogspot.co.uk/2016/06/three-ways-to-manage-your-resources-for.html
The full code source can be found here: https://github.com/Kimserey/SimpleUIWeb
That’s it, we are done. No more excuses to not build your own UI framework! Now your project will always remain up to date with your latest release of your UI framework!
Building a framework tailored to your needs, your own layout, your own components, your own interations and your own animations is a create way to improve and get a better sense of what can and has to be done. Of course, I am not promoting to reinvente the wheel but if you only need few components, don’t waste your time trying to find a gigantic framework, just write your own. In few hours, you will have a complete UI framework tailored for your needs. Combine that with WebSharper to easily build SPA with F# and Paket to always stay in sync with your latest releases and you have a very good candidate for the best setup to build SPA. Like always, you have any comment leave it here or hit me on Twitter @Kimserey_Lam. Hope you enjoyed reading this post as much as I enjoyed writing it. See you next time!