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
-
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
andclass
attributes are special, because they can be elegantly addressed by CSS rules. CSS inside thestyle
attribute will be applied to the element with high precedence. HTML elements define a default layout behaviour (block
- andinline
-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. -
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. -
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 functiondocument.getDivById()
, just a generaldocument.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:
Kommentar veröffentlichen