Blog-Archiv

Sonntag, 23. Juli 2017

Separate HTML, CSS and JS

The aunt of our chief-programmer has a cousin that has a son that just made the grade and now learnt CSS. He will come for two months and polish the CSS of the web-application we are working on.

Alarm bells ringing. Why are we afraid of that? Didn't we separate HTML from CSS and JavaScript cleanly, so that the guy can't break anything, whatever he may commit?

No, we didn't. We just tried to. It is not possible to separate these things completely (although some seem to believe that:-).

In this Blog I will go through some thoughts about decoupling HTML, JS and CSS.

Three Technologies

  1. HTML - a markup language for text and multimedia content, the main thing that makes up a web page. Restricted in its interactive capabilities (just HTML forms). It provides a hierarchical structure of document-elements , which can have attributes, of which the id and class attributes are special, because they can be elegantly addressed by CSS rules. CSS inside the style attribute will be applied to the element with high precedence. HTML elements define a default layout behaviour (block- and inline-elements) that can be changed by CSS only. Some elements like <table>, <ul> (list), <h1> - <h6> and <blockquote> are dedicated to layout, some like <b>, <i>, <code> etc. are dedicated to styling.

  2. CSS - a rule-based language that covers "skinning" (color, font, border-style) and layout (positioning, alignment, margin, border-thickness, padding, tables, resize- and scroll-behaviour). CSS also can add text or images to the page via the pseudo-element's content property.

  3. JavaScript (JS) - a typeless structured script language used to dynamically work on a web page, primarily intended for processing user inputs, but it can do nearly everything with the web page. A JS interpreter is built into any browser, and it is instantiated for every displayed page. That means when you reload a page, its JS engine is dismissed, and a new one is created (dismissing all global variables). JS engines can not access sibling pages in the browser. JS can read and write CSS, thus it does not have an element.setForegroundColor() function. JS works with HTML elements generically, that means there is no type-specific function document.getDivById(), just a general document.getElementById().

Separation of Concerns?

What are the concerns?

  • Content
    expected in HTML

  • Layout
    expected in .... CSS? HTML?

  • Styling (skinning, the "Look" of Look & Feel)
    expected in CSS

  • Interaction (keyboard and mouse responses, the "Feel" of Look & Feel)
    expected in JavaScript

Hard to keep these expectations.

HTML

An HTML div block-element affects layout differently than a span inline-element, and a CSS property like width will not work any more when changing the type of its targeted element from div to span. HTML table specifies layout, as lists do (ul, ol, dl).

This is the biggest weakness of web-pages:

  • Layout has not been confined as a separate aspect

Although it is so important. We should have given it its own domain-specific language! Instead it is in both HTML and CSS.

Have you ever tried to set a text-field disabled using CSS? It is not possible. You need to do this using the HTML attribute disabled.

CSS

CSS addresses elements using rules, evaluated dynamically. But rules never can be really precise. HTML elements could have been added to the document, not being addressed by out-dated CSS rules. Thus errors always will be present where rule engines are working. The browser does not report them.

Although CSS is a programming language, it does not provide even basic means, which is the use of variables and arithmetic operations. That makes up the second weakness of web-pages:

  • CSS is so weak that it forces code duplications

Clever developers recommend that CSS should be applied through CSS classes only. That means, do not write CSS into the style attribute of HTML elements, just put a CSS-class identifier into the HTML element's class attribute and apply CSS that way.

Now when you look at actual web pages, you won't find a "definition" of a CSS class (like in Java or C++). A CSS class is just an identifier that tries to express a responsibility, and it is used in CSS rules, together with other criteria, and it is used in class attributes, together with other CSS classes. Where should programmers document the CSS classes that they have created?

  • There is no place for defining and documenting CSS classes

I consider self-documenting code to be a myth. The name alone is not enough, we need context.

Some people may also have spent a lot of time by internationalizing texts that were coded into the content property of pseudo-elements. Text definitely is not the responsibility of CSS, is it?

CSS even provides a very primitive kind of event listening through pseudo-classes. CSS menus are made of this, and their designers still consider them to be user-friendly.

JS

JavaScript finally is the tool that can manage everything. But you create lots of dangerous dependencies when writing JS code for a web page. You may anticipate a certain HTML element structure that is changed the very next months by a web designer. Same with CSS. From JS you can easily set styles on elements, but these will overrule what the web designer has put on them.

Now there are tips about how to separate JS and CSS. JS should add or remove CSS classes on the element, but never directly define any CSS property. So, never do element.style.color = "red" in JS, because this may not comply to the CSS theme.

But what about statements like element.style.width = "20em"; where 20 is a calculated width? Or does it makes sense to use a CSS class display-none for making an element disappear (like you would do in JS via element.style.display = "none"), when a CSS designer could turn this afterwards to display-none { visibility: "hidden"; }? This definitely changes the layout behaviour, which may not have been the intent of the JS programmer.

  • Keeping CSS out of JavaScript makes sense only for skinning (color, font), but not for layout

JavaScript is the almighty power in a web page. It can do everything. It will be hard to keep HTML and CSS out of it.

So What Should We Do?

Although it is not an overall solution, CSS classes are a way to achieve a minimum of decoupling. Never use the style attribute of an HTML element, better add a CSS class identifier to its class attribute. Then try to have that CSS class identifier alone on the left side of the CSS rule, not mixed with other criteria. That way you also have a place where you could document the CSS class, which is absolutely needed.

Avoid complex selectors in CSS and JS. Instead put CSS classes onto HTML elements extensively, and find descriptive names for them.

A CSS class should have just one responsibility. If there are more things to do, create further CSS classes. Keep their names according to the responsibility, and try to stay simple and human-readable.

Now there are advices to use prefixes for CSS classes. The prefix should express whether the class is used as JavaScript hook or for CSS styling. That is a good idea.

But concerning prefixes, this is also the only way to make CSS "local". In other words, we should use a constant CSS class prefix for our web-application, so that we can keep our CSS apart from common CSS libraries like bootstrap. There is even more to this, because we compose our application from components that also have names, and we would like to know which component the CSS on our single-page-application comes from.

Summarizing this, here is my CSS class prototype:

/**
 * Gray out the element.
 */
.myapp_mycomp_css_gray-out
{
  opacity: 0.6;
}

Prefixes explained:

  • _
    using underscore "_" as prefix-separator to reserve dash "-" for the responsibility

  • myapp
    distinguishes it from CSS that does not care about other CSS (like bootstrap)

  • mycomp
    we need to know which reusable component this comes from

  • css
    expresses that this CSS class is not used by JavaScript, e.g. to install event listeners

  • gray-out
    the responsibility of the CSS class

Don't say this is ridiculous. It is the consequence of 20 years web development :-)

Summary

Things are getting better. SCSS is relieving the lack of variables and arithmetic in CSS. ES-6 will make JS a better programming language. But will this really help us to decouple HTML, CSS and JS in our web pages?




Keine Kommentare: