Front-End Tooling Trends 2018 Plus... CSS Preprocessor Intro - ByteScout
  • Home
  • /
  • Blog
  • /
  • Front-End Tooling Trends 2018 Plus… CSS Preprocessor Intro

Front-End Tooling Trends 2018 Plus… CSS Preprocessor Intro

Front-end development tools and techniques evolve rapidly, but we must stay on top of them to keep a competitive edge and extract superlative performance from websites and apps. To achieve this goal ByteScout presents emerging front-end tooling trends going into 2018, along with an intro to CSS Preprocessors versus native CSS code. To begin, let’s digest the stats on the tools most used in the field. Although there is no absolute guarantee of the endurance of these tools in the future, there is strength in numbers. JQuery is merely a JavaScript library. But because of its ubiquity JQuery regularly appears alongside JavaScript language with requisite skill lists for front-end development projects.

JavaScript Libraries: The Wildest Frontier

JQuery remains the most frequently used library for simplifying HTML development. So predominant is JQuery that it influenced the design of Dojo, which abstracts the differences between browsers so that one API codes for all of them. At least 70% of websites use JQuery and as a result, several industries leading software vendors bundle JQuery on their platforms. JQuery’s standard DOM selectors engine, called “Sizzle,” motivated the creation of Selectors API. Although less prolific than JQuery, hundreds of important JavaScript libraries demand our attention to stay abreast of the direction of high-performance development in 2018. Modernizr is a clever example.

Modernizr intercepts and corrects compatibility issues by first detecting a script’s use of unimplemented HTML5 and CSS3 features and deploying a remedy such as a shim. More than 10% (and growing) of all websites deploy Modernizr, and this type of compatibility mediator gains importance with each increasingly complex release of new HTML, CSS, and JavaScript features, and this serves two related functions. It frees the developer from worrying whether an app feature is supported, and at the same time compensates for yet unimplemented features. Consider this Modernizr example.

Suppose you include Modernizr’s CSS gradients detection. A browser will return <html class=”cssgradients”> or <html class=”no-cssgradients”>. Knowing this in advance we can include this CSS code to catch either case:

.no-cssgradients .header {
background:url(images/abutton.png);
}
.cssgradients .header {
background-image:linear-gradient(DarkTurquoise,DarkSlateGray);
}

Now, let’s scan through the rich functionality offered by some of the most popular JavaScript libraries. React is a JS library dedicated to building User Interfaces. A React UI can manage its own state. Components may implement a render() method which takes some input data and returns an output to display dynamically. Consider this timer display suggested by React creators in which input data is accessed via this.props:

class myTimer extends React.Component {
  constructor(props) {
    super(props);
    this.state = { seconds: 0 };
  }

  tick() {
    this.setState(prevState => ({
      seconds: prevState.seconds + 1
    }));
  }

  componentDidMount() {
    this.interval = setInterval(() => this.tick(), 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return (
Seconds: {this.state.seconds}
); } } ReactDOM.render(, mountNode);

React components maintain internal state data accessed in the snippet above via this.state. Each time the component’s state data changes, the markup updates by automatically re-invoking render().

We need to commit significant time and effort to complete even a brief survey of the proposed list of libraries! Bootstrap, MooTools, Underscore, Prototype, Moment.js, Backbone, Lodash, Zepto, Shadowbox, Vue.js, Polymer, Ember, Spry, and Knockout are all noteworthy JavaScript libraries. Each of them is used on more than 100 million websites worldwide according to Web 3 Tech stats. Here is a very brief description of each of these popular JavaScript libraries to whet your appetite:

Bootstrap is a front-end JS framework used for easier and quicker web development. It has HTML and CSS templates, forms, buttons, tables, modals, and many more features, including JavaScript plugins. Mootools competes with JQuery to offer a collection of JavaScript utilities intended for more advanced JavaScript developers. It includes many well-documented and coherent APIs. Underscore is a JavaScript library providing utility functions for typical coding tasks and is similar in functionality to Prototype.js and Ruby.

A prototype is an open-source framework that facilitates cross-browser development. Moment is a JavaScript date library for parsing and manipulating dates. Backbone is a library with a RESTful – JSON interface designed for creating single-page web applications and for synchronizing multiple client apps. Lodash has a lot of functionality in common with Underscore.js and the same developers maintain both libraries. Zepto is a minimalist library for modern browsers which is a subset of JQuery. If you know JQuery then you can use Zepto. Shadowbox is an app that supports online media viewing for all popular media formats. Vue.js is an open-source progressive framework for creating user interfaces. Polymer is designed for building web applications using Web Components. The library is maintained by Google. Ember enables you to create apps with much less coding and includes Handlebars and integrated templates that automatically update whenever underlying data changes. Spry is an open-source Framework is open-source Ajax framework developed by Adobe Systems which is used in the construction of Rich Internet applications. Spry is intended for web designers rather than web developers. And there may be 20 or so more libraries in the category of “used on over 100 million websites!”

While certain JavaScript libraries like React have the special purpose of facilitating the creation of UIs, there are JS libraries that actually seek to expand JavaScript itself to an infinitely richer and more robust coding language. Among these are AJAX and AngularJS. AngularJS extends the standard attributes of HTML with Directives and binds data to HTML attributes with Expressions. More than 500 million websites make use of this rich functionality to create increasingly dynamic applications. 

Debugging on the Wild Front-End Frontier

What better way to debug a script that to run it in actual context on one of the most popular and recently optimized browsers while that browser’s developer tools are open? Firefox’s Node Picker enables you to pick a page element currently running in the browser view and instantly look at the underlying code. Style Editor, Profiler, Network Monitor, Web Console, and JavaScript Debugger are among the freeware browser’s front-end debugging tools. Beyond the native tools, hundreds of clever Add-ons such as Web Developer enables you to display and edit CSS by media type. Firefox Developer Edition has features including CSS Grid support and framework debugging.

Generally, lint tools perform static analysis of source code and flag errors. CSS Lint detects errors in CSS code through syntax checking and application of customizable rules. Patterns of errors and possible inefficiency can be detected. As CSS libraries arise from the efficient use of preprocessor languages like Sass and Stylus, developers may rely on debugging tools like CSSLint, which is an open-source freeware tool. JSHint provides an analogous linting tool to determine if JavaScript complies with coding rules. These and many other debugging tools are available on their associated GitHub repositories.

Testing and debugging includes behavior-driven development systems. These BDDs emerged to check script behavior live in a browser to make front-end testing more practical. Mocha is the most popular of the BDDs, with Jasmine a near second, and QUnit in third place moving toward the new year.

Git’ing to the Grunt Work

Task runners automate and streamline the build process for developers, and this category of tools features JavaScript libraries Gulp and Grunt. Gulp is the current favorite by far, claiming nearly 50% share in this tool category going into 2018. Gulp streamlines repetitive tasks common to web development such as concatenation, minification, optimization, unit testing, cache busting, linting, and more. Gulp is built on NodeJS and npm and has more than 300 plugins to facilitate these tasks. Install with npm install –save-dev gulp-jshint and to run this sample type gulp jsLint :

// include plugin
var gulp = require('gulp')
, jshint = require("gulp-jshint");
// tasks
gulp.task('jsLint', function () {
gulp.src('./JavaScript/*.js') // path to my files
.pipe(jshint())
.pipe(jshint.reporter()); // results
});

When the setup is correct a static analysis of your JavaScript code will result in a list of any standard coding errors found by JSHint.

JavaScript recently migrated to server-side coding on the coattails of NodeJS and several module bundlers for JS server-side use Lasso.js is a module bundler that facilitates the development of deep server-side JavaScript libraries. As we enter the 2018 new year, Wolfpack is the clear leader in this group of tools. Browserify and Lasso.js are noteworthy and have captured smaller slices of the developer pie. For more, see ByteScout’s “Ultimate Lasso.js Tutorial.”

Intro to CSS Preprocessors

And now for the featured front-end tool of this ByteScout survey, let’s get into an introduction to CSS preprocessor coding with some practical examples. CSS preprocessors such as Stylus and Sass are scripting languages that seek to extend CSS and then compile their own unique syntax and native code into regular CSS. I use “seek” because native CSS now includes a lot of features the lack of which preprocessor design intended to compensate us for.

There is some competition between CSS native and preprocessor features, the scope of variables, and mixins for example, and there is significant debate among developers about which is best. Indeed, the debate itself suffers from the confusion caused by variations in which new features are supported by which browsers. The debate is further convoluted by a sea of JavaScript workarounds on both sides. So, let’s look at some examples of each in an effort to explore and illuminate.

Developer criticism includes the issue that CSS preprocessor variables are static and have lexical scope, whereas native CSS variables are dynamic and are scoped to the DOM. Variables are actually embodied in CSS properties. A common application where a variable scoped to the DOM is to create a layout with variable spacing for a gutter to accommodate different browser window sizes. This task is difficult for Sass, the most popular CSS preprocessor going into 2018, but it is more easily done with native CSS custom properties. Here is a layout with three window size variations:

/* Declare `--gutter` at each breakpoint */
:root { --gutter: 1.5em; }
@media (min-width: 30em) {
:root { --gutter: 2em; }
}
@media (min-width: 48em) {
:root { --gutter: 3em; }
}

/*
* Styles are defined once because of custom property values auto-update.
*/

.Container {
margin: 0 auto;
max-width: 50em;
padding: var(--gutter);
}
.Grid {
--gutterNegative: calc(-1 * var(--gutter));
display: flex;
margin-left: var(--gutterNegative);
margin-top: var(--gutterNegative);
}
.Grid-cell {
flex: 1;
margin-left: var(--gutter);
margin-top: var(--gutter);
}

Now let’s look at the same method using Sass preprocessor. Sass variables don’t work with media queries (because Sass is not actually operable in the browser) each of the three layout variations above must be coded as:

/* Declare the three gutter vals above for each breakpoint */

$gutterSmall: 1em;
$gutterMedium: 2em;
$gutterLarge: 3em;

/* Base style for small screen, using $gutterSmall. */

.Container {
margin: 0 auto;
max-width: 50em;
padding: $gutterSmall;
}
.Grid {
display: flex;
margin: -$gutterSmall 0 0 -$gutterSmall;
}
.Grid-cell {
flex: 1;
padding: $gutterSmall 0 0 $gutterSmall;
}

/* Override styles for medium screens, using $gutterMd. */

@media (min-width: 30em) {
.Container {
padding: $gutterMedium;
}
.Grid {
margin: -$gutterMedium 0 0 -$gutterMedium;
}
.Grid-cell {
padding: $gutterMedium 0 0 $gutterMedium;
}
}

/* Override style for large screen, use $gutterLarge. */

@media (min-width: 48em) {
.Container {
padding: $gutterLarge;
}
.Grid {
margin: -$gutterLarge 0 0 -$gutterLarge;
}
.Grid-cell {
padding: $gutterLarge 0 0 $gutterLarge;
}
}

Although it may be odd to build a preprocessor intro on the basis of a method that actually works better in native CSS, the knowledge of the differences and practical applications where the methods of one are stronger than the other will serve us better than developing prejudicial ideas leading to the rigid adoption of a one-track development approach. Until there is a universal CSS browser standard, The silver bullet is flexibility! We need to use both CSS and preprocessors.

Next on the preprocessor feature list is the mixin. A mixin enables the creation of groups of CSS declarations that you can reuse throughout your website. Let’s compare a Sass and a native CSS mixin. Later, we will look at the feature differences of some of the preprocessors too. First, have a look at this native CSS mixin:

/* Native CSS */
:root {
--my-mixin: {
background: #256bbd;
color: #f5f5f6;
}
}
body {
@apply --my-mixin;
}

Now here is the same idea in Sass:

// Scss preprocessor
@mixin my-mixin {
background: #256bbd;
color: #f5f5f6;
}

body {
@include my-mixin;
}

Native CSS enables the creation of reusable modules. Sass supports the use of arguments. It supports passing a list of locally defined variables to a mixin. The native CSS @apply rule does not, and furthermore, the consensus is that @apply is not consistently supported across browsers. The significance depends on the application, and so developers will make an informed choice for their requirements.

If native CSS code appears equal to or better than preprocessors keep in mind that preprocessor code ultimately must be compiled to CSS. Whether or not the compiler is as ingenious as an experienced coder working directly in native CSS is too idealistic; preprocessors have their unique and highly beneficial features. So, let’s have a look at a few of the most popular ones.

The Preponderance of Preprocessors

Let’s compare the three most popular preprocessors moving into the new year in order: Sass, LESS, and Stylus. Each one has a slightly different method of implementing mixins. When a mixin is called from within a selector the styles defined in the mixin are then applied to the selector. This is very useful for the specialized styling of elements. Mixins thus make possible the reuse of properties throughout a stylesheet. Let’s compare the same common task across all three preprocessors, beginning with the Sass @mixin:

/* Sass error mixin optional argument $borderWidth defaults to 2px if unspecified */

@mixin error($borderWidth: 2px) {
border: $borderWidth solid #F00;
color: #F00;
}

.generic-error {
padding: 20px;
margin: 4px;
@include error(); /* Apply style from error mixin */
}
.login-error {
left: 12px;
position: absolute;
top: 20px;
@include error(5px);
}

Sass variables begin with $ and we delimit value and name with a semicolon as with CSS properties. Here is the same mixin in LESS beginning with .error:

/* LESS error mixin optional argument @borderWidth defaults to 2px if unspecified */

.error(@borderWidth: 2px) {
border: @borderWidth solid #F00;
color: #F00;
}

.generic-error {
padding: 20px;
margin: 4px;
.error(); /* Apply style from error mixin */
}
.login-error {
left: 12px;
position: absolute;
top: 20px;
.error(5px);
}

LESS variables begin with the @ symbol. Now have a look at the variation of syntax and variable names in the same code in Stylus:

/* Stylus error mixin optional argument borderWidth defaults to 2px if unspecified */
/* No variable prepend symbol */
error(borderWidth= 2px) {
border: borderWidth solid #F00;
color: #F00;
}

.generic-error {
padding: 20px;
margin: 4px;
error(); /* Apply style from error mixin */

}
.login-error {
left: 12px;
position: absolute;
top: 20px;
error(5px);
}

Stylus variables don’t use a prepended symbol, and an equal sign assigns value to variables. Global variables in preprocessors assign variables representing attributes including color. We can assign a color once and later easily change a single style of the entire site with a quick edit to one variable value!

Ultimately, all three of the above compile to the same native CSS code:

.generic-error {
padding: 20px;
margin: 4px;
border: 2px solid #f00;
color: #f00;
}
.login-error {
left: 12px;
position: absolute;
top: 20px;
border: 5px solid #f00;
color: #f00;
}

Inheritance works in all three preprocessors so that we can apply the same style to multiple elements at the same time, and one CSS selector can then inherit the properties of another selector. Note that LESS does not support inheritance in the same way as Sass and Stylus, but rather like mixins which import styles into selectors.

Looking at some pre-processor built-in functions which provide real advantages over native CSS, Sass supports a variety of functions for creating color gradients. The colors in these variables will be lightened or darkened:

lighten($color, 10%);
darken($color, 10%);

LESS functions are the same, remembering to change the $ to @ for variable names. For Stylus simply remove the prepended symbol. And let’s look at another syntax issue of the pre-processors.

Nesting works the same way to improve CSS syntax in all three preprocessors. For example, there is no need to repeat the same parent for a selector asn this CSS example:

section {
margin: 12px;
}
section nav {
height: 24px;
}
section nav a {
color: #0982D1;
}
section nav a:hover {
text-decoration: underline;
}

Because the preprocessor syntax resembles normal or familiar JS syntax as in this Sass example (equivalent to above) :

section {
margin: 12px;

nav {
height: 24px;

a {
color: #0982D1;

&amp;:hover {
text-decoration: underline;
}
}
}
}

The Final Word on Preprocessors

Sass and the other preprocessors add rich features to facilitate writing and maintaining CSS stylesheets. But preprocessors add one very important conceptual capability known as DRY (don’t repeat yourself.) While CSS alone can be cumbersome with frequent duplication of common sets of properties, developing stylesheets with preprocessors enables cleaner coding practices because they are more like real programming languages, with conditional logic, loops, and functions. DRYing code can improve website performance too.

Taking account of all the benefits of preprocessors we discover, perhaps to some surprise, that we must still retain expert knowledge and familiarity with native CSS code. First, we must have the fundamental knowledge to know when native CSS is actually better for a task than preprocessor compiled CSS. And secondly, we must have the ability to map preprocessor output to browser behavior in order to debug and fine-tune results. The final word on the subject is that developers must study and practice with diligence to stay abreast of the potential for rich CSS stylesheet creation opened up by preprocessors heading into the new year.

   

About the Author

ByteScout Team ByteScout Team of Writers ByteScout has a team of professional writers proficient in different technical topics. We select the best writers to cover interesting and trending topics for our readers. We love developers and we hope our articles help you learn about programming and programmers.  
prev
next