CSS namespaces (If you’re not scared of XML)

I’ve been looking at the CSS in JS debate for a while and one of the things that still surprises me if that people go to all these lengths to create and use namespaces for their elements when there’s a way to do it already baked in the platform.

If you’re not allergic to XML and you’ve been around the web for a while you know what XML is and you may be one of those who have developed phobia to XML (you have an x-girlfriend) to not want to use it and do everything in JSON.

But there are times when XML is necessary and I believe this is one of those situations. XML Namespaces provide an easy way to disambiguate elements with the same name.

A namespace is a unique URI (Uniform Resource Locator) that qualifies and disambiguates elements. The URI must be to a valid domain but it doesn’t have to point to anything concrete. In the example below we create 2 namespaces, a default one for (x)html and one for svg.

Granted, this is a contrived example because in HTML5 known foreign elements are automatically assigned to their respective namespaces. This means that HTML elements will act as though they are in the XHTML namespace (http://www.w3.org/1999/xhtml), and the <svg> and <math> elements will be assigned their proper namespaces (http://www.w3.org/2000/svg and http://www.w3.org/1998/Math/MathML).

As contrived example as this is, it illustrates how we can use Namespaces in CSS.

@namespace url(http://www.w3.org/1999/xhtml);
@namespace svg url(http://www.w3.org/2000/svg);

/* 
  This matches all XHTML <a> elements, as XHTML 
  is the default unprefixed namespace 
*/
a {}

/* 
  This matches all SVG <a> elements
*/
svg|a {}

/* 
  This matches both XHTML and SVG <a> elements 
*/
*|a {}

I usually create a special domain to park namespaces and other esoteric elements like applications that need their own namespace or that point to a specific DTD or XML Schema.

For my current domain the site is https://ns.rivendellweb.net. The site is a legal one and it can have as many namespaces attached to it as we need. Take a look at the example below:

@namespace svg url(http://www.w3.org/2000/svg);
@namespace media url(https://ns.rivendellweb.net/media/);
@namespace grid url(https://ns.rivendellweb.net/grid/)

/*
  This element is implicitly in the XHTML namespace
*/
body {
  color: blue
}

/*
  This class is in the media namespace
*/
media|div.container {
  margin: 0 auto;
}

/*
  This class is in the grid namespace

  Eventhough it has the same name as the one above
  it's treated differently because it's in a separate
  namespace.
*/
grid|div.container {
  display:grid;
}

Before you jump in and say that this is not going to work let’s look at how it works. We’ll use the same style sheet we created above and the markup shown in the example below:

<doctype html
<html
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns:media="https://ns.rivendellweb.net/media/"
  xmlns:grid="https://ns.rivendellweb.net/grid/"
  xmlns:mathml="http://www.w3.org/1998/Math/MathML">
  <head>
    <title>My awesome page</title>
    <link rel="stylesheet" href="css/styles.css">
  </head>
  <body>

    <h1>The page title</h1>

    <media:div class="container">
      <video src="video/my-video.mp4">
    </div>

    <grid:div class="container">
      <p>Grid content will go here</p>
    </div>
  </body>
</html>

The idea is that in both markup and CSS we prefix the content with namespaces that will only match when both the namespace and the element match. That’s why we can get away with having two container elements that do completely different things… they are in different namespaces so we can get away with this.

To ensure the content validates we declare the namespace prefixes in the root element of the page, in this case the html element.

A side benefit of using namespaces this way is that we can shorten our selectors. Rather than use classes to describe the selector as we do with BEM we can declare additional namespaces to structure our content.

The one downside I see is the verbosity we must use when creating new classes and elements in a namespace. It’s not enough to write div.container to indicate a div with a class of container. Unless we’re working in the html/xhtml namespace we must qualify the element like media|div.container or grid|div.container in css and <media:div class="container"> or <grid:div class="container">. If you’re totally into squeezing the most of your compressed content this may not work as it adds bytes that you may consider unnecessary.

Other developers may consider the prefix requirement to be a downside. As I mentioned earlier, I don’t have an issue with using prefixes as I’ve worked extensively with XML so namespaces are ok with me.

The final issue to consider is that using namespaces other than a few namespace+attribute combinations described in the HTML5 Specification syntax section (section 8.1.2.3) requires you to write documents using XHTML syntax. I’m ok with this but may bug you if you think that tag soup documents are ok (I don’t).

Blockly as a programming teaching tool

One of the first things that brought me to programming was Logo back in the mid 1980’s. It wasnt the structure of the programs that you could type stuff that would make things happen on the screen. To me the magic was that you could share and that typing the same things would always produce the same results so you could iterate and do even crazier things with your designs.

If running the following commands:

repeat 4
forward 90

would create a square what would happen if we started moving the turtle around without drawing anything and then run our square command? How would we write circles? Triangles? Other geometrical shapes?

This has always motivated my interest in computers, the web, and odball projects that will make something interesting but not necessarily useful. It’s curiosity, the desire to know how to do something even if there are better ways to do it.

Move forward about 30 years and I found Scratch and I found myself thinking back to Logo and my experiences with old computers at school.

But it looks different and it uses a different paradigm to create the scripts that will make things happen. The first figure shows an animated example created with Scratch and the second shows a more technically complex example using the same language.

Scratch 2.0 screenshot
More complex example of Scratch

Wouldn’t it be cool if we could leverage these technologies to serve children and other people coming into code with a less threatening introduction to programming? Coding is not hard, figuring out the rules behind code is more complicated, at least it was to me.

That’s where I think Scratch and similar tools can be useful. Google released a set of coding tutorials using Wonder Woman and Blockly, a Scratch-like application to make teaching computer science concepts easier for children.

The figure below shows an example of what one of the Wonder Woman based tutorials look like: you assemble the tasks for Wonder woman using blocks and then play the actions represented by the blocks we’ve assembled together.

Wonder Woman Coding Tutorial

How can we leverage these tools for a larger audience? How can we make a programming environment that gives us both the advantage of Blockly/Scratch and allows us to copy and paste the resulting code in one of many programming languages.

Blockly has several advantages: it allows you to see the results of your block actions in the target language of your choice. The currently supported languages are:

  • Javascript
  • Dart
  • PHP
  • Lua
  • Python

In the configuration we can create groups of blocks to show users.

We can configure Blockly to show only a few block or the entire set.

We can also create custom blocks that better fit the language we want to teach or the session’s objectives.

It can be configured to run on Google’s App Engine. This will create a community where scripts will be automatically saved and shared with the community.

Let’s build a Blockly app.

Building Basics

Download the code or clone the Git repository from:

https://github.com/google/blockly

If you downloaded a compressed version of the files expand them and get them ready. We’ll come back to them to build the directory structure for o ur application.

Blockly is built with Javascript, Node/NPM and Google’s Closure Compiler. I will not cover how to build the app… You can rebuild the scripts on your own if interested.

We’ll start with the most basic Blockly app. It is a simple HTML page where we insert a series of elements to make Blockly work.

The first part is to add Blockly an associated scripts for the page:

  • Blockly itself
  • A basic set of blocks
  • The Javascript syntax file
  • English translation of Blockly’s messages
<script src="js/blockly_compressed.js"></script>
<script src="js/blocks_compressed.js"></script>
<script src="js/javascript_compressed.js"></script>
<script src="msg/js/en.js"></script>

We then set up two empty elements: A div that will hold the blocks and the work area, and a text are that will hold the Javascript version of the block code.

<div id="blocklyDiv"
      style="height: 600px; width: 800px;"></div>
<textarea id="textarea"
          style="width: 800px; height: 300px"></textarea>

The next postion is an xml element that will hold the block elements that we want to use in our application.

<xml id="toolbox"
      style="display: none">
  <block type="controls_if"></block>
  <block type="controls_repeat_ext"></block>
  <block type="logic_compare"></block>
  <block type="math_number"></block>
  <block type="math_arithmetic"></block>
  <block type="text"></block>
  <block type="text_print"></block>
</xml>

The final portion is the script that will make everything work. This is also broken in three sections.

The first part injects Blockly with the toolbox we defined earlier.

The next function defines how Blockly will update the text area with the result of coverting the blocks into Javascript.

Finally we add a change listener and tell it to run myUpdateFunction every time it’s triggered.

<script>
var workspace = Blockly.inject('blocklyDiv', 
{toolbox: document.getElementById('toolbox')}); 

function myUpdateFunction(event) { 
  var code = Blockly.JavaScript.workspaceToCode(workspace); 
  document.getElementById('textarea').value = code;
}
workspace.addChangeListener(myUpdateFunction);
</script>

That’s it. We have a Blockly application that will convert the blocks into Javascript. However it won’t save the code and provides no way of sharing it. We’ll tackle that challenge next.

Adding a backend server

Blockly comes pre-configured to work with Google App Engine (it’s a Google product, after all). For this section I will assume that you have some experience in configuring and installing applications in App Engine; if not I would recommend you find a good tutorial and go through it before continuing.

  1. Download and install the Python SDK
  2. Log into Google App Engine and create an application.
  3. Edit appengine/app.yaml and change the application ID from blockly-demo to the application name you created in the previous step.
  4. Copy (or soft-link) the following files and directories into appengine/static/:
    • demos/
    • msg/
    • media/
    • *_compressed.js
  5. Run the Google App Engine Launcher from the GUI, add your appengine directory as an existing application, and press the “Deploy” button. If you prefer to use the command line, run: appcfg.py --oauth2 update appengine/

Optional: If you’d like to use blockly_uncompressed.js on the server, also copy that file into appengine/static/, copy core into appengine/static/, and copy closure-library/ into the parent directory, appengine/.

Optional: If you’d like to run the Blockly Playground, you’ll have to copy the blocks, generators, and tests directories, as well as the files in the prior optional step.

Note that the Google App Engine Launcher has been deprecated and a replacement has not been implemented or made official. That said I could get away with using an older version of the App Engine Launcher and deploy the application.

You can find it at https://blockly-demo-171420.appspot.com/

The demos will show you the capabilities of Blockly beyond what we’ve discussed so far. Now that we have the tools we can talk a little bit about philosophy.

Why use Blockly?

When we start looking at Blockly one of the first things to consider is who is our target audience. I’ll apply an ADDIE model to suggest ideas about how to use Blockly in an educational environment.

Analysis:

We’re building an application that will make it easier to learn programming.

These Blocky applications can be targeted towards younger users who are learning to program and interact with code for the first time and also for older users who have not had formal programming experiences.

Design:

Depending on how we want to structure the learning experiences we can either create individual Blockly pages like the Made with Code Wonder Woman’s Examples where you limit the number of blocks you can use and also the type of blocks a given page has access to.

For older users or those children who have mastered the more limited concepts we can also provide a larger set of blocks to experiment with.

Finally, if we’re working with frameworks we can generate custom blocks that will do specific tasks. For example, if we’re using Blockly to teach web components concepts we can create blocks that will translate to class-based custom elements.

Development:

Before we modify any of the blocks and create pages we need to know what the breakdown for the pages is: what blocks are they using and what is our objective for that particular page.

Once we do we can take some of pages on the demo site and modify them to match our goals. We can also theme the pages to a common look and feel.

Implementation:

Implementing the pages is easy. We can start from scratch or we can clone an existing demo page that has the features we need and modify it to suit.

At the server level we must make sure to change the version of the application in the app.yaml configuration file. This will allow us to deploy multiple versions of the blocks and pages to App Engine without loosing the ability to rollback if there is a problem.

Evaluation:

I think evaluation of Blockly projects is mostly outcomes based. Did they participant’s learn? Did they enjoy themselves in the process? Can they translate the content they learned into other areas and domains?

Links and References

Creating an In-Browser Editor

One thing that blew my mind was a web-based slide deck that changed a style’s CSS when you edited the CSS block shown as text in the slide. Think about it… We can change the CSS of our content as we need to just by editing the CSS inline, in the same browser that is displaying the content we are styling. Awesome!

Later on I changed my mind a little. CSS is too much of a pain but what if we want to change a document or create a new one and then save it or do some further processing with it.

In this post I’ll cover things like contenteditable, execCommand, other ways to create and add content to our editable regions and how to package an editor into a web component.

What do we want to do

Before diving into the technology let’s talk about what we want to do for a second, It’s always a good idea to have a spec before we start doing the work so we won’t loose sight of the final objective.

I want to build an inline editor that will let me edit CSS, Javacript and HTML. Think of a limited version of Netscape Composer but inline in the browser rather than being a separate application.

I want to be able to type content directly in the editor and have buttons that will let me insert some HTML tags on their own or over highighted content.

Some functionality

At it’s simplest we can make a section editable by adding the contenteditable="true" attribute to the element we want to make editable.

<div class="editor-container" contenteditable="true">
 <p>This is the editor</p>
</div>

We can change the content of the editor, but that’s about the extent of it. However this will change if we start working with styles. Take the following style element placed inline in a page’s body.

<style>
  body {
    font-size: 1.5em;
    font-color: black;
  }
</style>

In your master stylesheet make the style sheet visible by changing its display to block.

style {
  display: block
}

This will make the stylesheet visible in your document but will still work styling the content. One last change to make, make the style element editable.

<style contenteditable="true">
  body {
    font-size: 1.5em;
    font-color: black;
  }
</style>

In this 3-step process we’ve created a basic CSS editor for the page it is running on. It will only work on the page we place the styles and, right now, we can’t save the styles.

We’ll create a button to edit the content and wire it to enable and disabling content editable; When we make the content non editable we make sure we save the content in local storage.

const editBtn = document.getElementById("editBtn");
const editable = document.getElementById("editor-content");

editBtn.addEventListener("click", function(e) {
  if (!editable.isContentEditable) {
    editable.contentEditable = "true";
    editBtn.innerHTML = "Save Changes";
    editBtn.style.backgroundColor = "#6F9";
  } else { // Disable Editing
    editable.contentEditable = "false";
    editBtn.innerHTML = "EDIT CONTENT";
    editBtn.style.backgroundColor = "#F96";
    saveContent();
  }
});

The save function is simple, is creates an item in local storage with key of the id for our editor (content-editor) and the data in the editor (the editor’s innerHTML) as it’s value.

function saveContent() {
  if (typeof(Storage) !== "undefined") {
  // Save the data in localStorage
  localStorage.setItem(editable.id, editable.innerHTML);
  }
}

If you save the changes and then reload the editor you will find that the editor will revert to the last time you saved it. That’s because there is a way to save the content not not to retrieve it.

To handle loading content from local storage wedo three things:

  1. We check that local storage is supported
  2. If it’s suppoorted then we check that there is a value that matches what we want to load (content-editor)
  3. We load the data inside the editor’s body

Yes, I’m being overtly cautious in checking if Local Storage is supported, both when saving and loading content. We could make a function out of the test but I’m comfortable doing it this way.

if (typeof(Storage) !== "undefined") { // 1
  if (localStorage.getItem('editor-content') !== null) { // 2
    editable.innerHTML = localStorage.getItem('editor-content'); // 3
  }
}

Right now we have a bare bones functional editor. We can write on it, we can save the data and when we return to it, we’ll be able to resume editing from where we left off. This is a good starting point but we can definitely do more.

Adding functionality

This is the most interesting part and also the most difficult to get working across browsers. document.execCommand() allows you to run a list of predefined commands insie your text editor. It takes three parameters:

  • The name of the command to run
  • Whether to show the default UI for the command (not supported in Firefox so we leave it as false throughout)
  • The parameter for the command, if needed. For example the URL for the image if we are inserting one

This is not a trivial undertaking and most times I would just turn to a canned solution like the ACE or TinyMCE editor systems but for the purpose of this article I Want to be able to add the functionality manually.

Because I want to add several commands we’ll have to get creative and use JSON as the data sourceand some creative use of JAvascript to generate the buttons and add them to the page.

The JSON file takes three elements:

  • The name of the command
  • The command itself
  • Any parameters for the command or null if there is none
const commands = [
  {
    "name": "p",
    "command": "formatBlock",
    "param": "p"
  },
  {
    "name": "h1",
    "command": "formatBlock",
    "param": "h1"
  },
  {
    "name": "h2",
    "command": "formatBlock",
    "param": "h2"
  },
  {
    "name": "h3",
    "command": "formatBlock",
    "param": "h3"
  },
  {
    "name": "h4",
    "command": "formatBlock",
    "param": "h4"
  },
  {
    "name": "h5",
    "command": "formatBlock",
    "param": "h5"
  },
  {
    "name": "h6",
    "command": "formatBlock",
    "param": "h6"
  },
  {
    "name": "Bold",
    "command": "bold",
    "param": null
  },
  {
    "name": "Underline",
    "command": "underline",
    "param": null
  },
  {
    "name": "Strike Through",
    "command": "strikeThrough",
    "param": null
  },
  {
    "name": "Remove Formatting",
    "command": "removeFormat",
    "param": null
  }
]

We then run the commands through array.map to perform the following actions:

  1. Create variables to hold each part of the command
  2. Create a button element
  3. Give it the name of the command
  4. Assing an ID attribute of the command itself
  5. Create an onclick event handles and use it to add a document.execCommand command for the appropriate element
var tb1 = document.getElementById('toolBar1');

commands.map(function(item) {
  var name = item.name; // 1
  var command = item.command;
  var param = item.param;

  var newButton = document.createElement('button'); // 2
  newButton.textContent = name; // 3
  newButton.setAttribute('id', command); // 4

  newButton.addEventListener('click', () => {
    document.execCommand(command, false, param) // 5
  });

  tb1.appendChild(newButton);
});

This method will provide a basic set of commands but will not handle some of the more complex cases like inserting images or hyperlinks.

I’ve chosen not to address these cases and leave them as exercise for the reader. There are commercial solutions like ACE or TinyMCE editor systems that do a much better job than I’ve done in this project and I’mm ok with that. This is a proof of contcept and will probably not go into much further development.

Links and resources

@font-face font-display property

There are times when the current solutions are not enough. Most of my non-Wordpress web content uses fontfaceobserver to handle web fonts and how they display on the page.

We’ve already used @font-face to load the fonts using CSS. The script below creates one instance of Fontfaceobserver for each of the fonts we’ve loaded using CSS.

Each FontFaceObserver instance has several methods that we’ll use later in the script.

We create a shortcut to document.documentElement to save ourselves typing.

The last command in this section will add a fonts-loading class to the page’s HTML element.

const mono = new FontFaceObserver('notomono-regular');
const sans = new FontFaceObserver('notosans-regular');
const italic = new FontFaceObserver('notosans-italics');
const bold = new FontFaceObserver('notosans-bold');
const bolditalic = new FontFaceObserver('notosans-bolditalic');

let html = document.documentElement;

html.classList.add('fonts-loading');

We use the load method of FontFaceObserver to create a promise for each of the fonts we are using and defined in the previous block. We then use Promise.all() to create an array of promises.

If all the promises resolve then we remove the fonts-loading CSS class and replace it with fonts-loaded.

If any of the promises rejects then Promise.all() will reject as well. In that case we replace fonts-loaded with fonts-failed.

Promise.all([ mono.load(), sans.load(), italic.load(), 
bolditalic.load()]).then(() => {
  html.classList.remove('fonts-loading');
  html.classList.add('fonts-loaded');
  console.log('All fonts have loaded.');
}).catch(() =>{
  html.classList.remove('fonts-loading');
  html.classList.add('fonts-failed');
  console.log('One or more fonts failed to load')
});

The classes we added in Javascript are also used in CSS to style the content. The first class is the default and uses system fonts so we don’t have to wait for web fonts to download.

The second class will only match when web fonts fail to load. It uses the same stack as the default.

The third class will match when web fonts load successfully and use the web fonts we just verified.

/* Default body style */
body {
  font-family: Verdana, sans-serif;
  font-size: 16px;
  line-height: 1.375;
}

/* This will match if the fonts failed to load. It is identical to the default but doesn't have to be*/
.fonts-failed body {
  font-family: Verdana, sans-serif;
  font-size: 16px;
  line-height: 1.375;
}

/* This will match when fonts load successfully */
.fonts-loaded body {
  font-family: notosans-regular, verdana, sans-serif;
  font-size: 16px;
  line-height: 1.375;
}

The font-display property provides predefined behaviors for web font downloading. It can take one of four possible values:

  • auto: The font display strategy is defined by the user agent. This means that it will do whatever it does normally
  • block: Gives the font face a short block period and an infinite swap period
  • swap: Gives the font face no block period and an infinite swap period
  • fallback: Gives the font face an extremely small block period and a short swap period
  • optional: gives the font face an extremely small block period and no swap period

We need to further define what we mean by block, swap and failure periods of font loading and what’s their sequence:

  1. The first period is the block period. During this period, if the font face is not loaded, any element attempting to use it must instead render with an invisible fallback font face causing a Flash Of Invisible Text. If the font face successfully loads during the block period, the font face is then used normally.
  2. The swap period occurs immediately after the block period. During this period, if the font face is not loaded, any element attempting to use it must instead render with a fallback font face. If the font face successfully loads during the swap period, the font face is then used normally.
  3. The failure period occurs immediately after the swap period. If the font face is not yet loaded when this period starts, it’s marked as a failed load, causing normal font fallback. Otherwise, the font face is used normally

Understanding these periods means you can use font-display to decide how your font should render depending on whether or when it was downloaded. There may be situations where performance is you most important concern so a more agressive strategy is necessary but there may be other instances where we want the content to display with our web fonts and performances is a secondary concern.

If all browsers worked the same way we wouldn’t have any problems and we could use font-display with no major issue. But not all browsers work the same; The table below shows how browsers behave regarding fonts download.

Browser Timeout Fallback Swap
Chrome 35+ 3 seconds Yes Yes
Opera 3 seconds Yes Yes
Firefox 3 seconds Yes Yes
Internet Explorer 0 seconds Yes Yes
Edge 0 seconds Yes Yes
Safari No timeout N/A N/A
  • Chrome and Firefox have a three second timeout after which the text is shown with the fallback font. If the font manages to download, then eventually a swap occurs and the text is re-rendered with the intended font.
  • Internet Explorer has a zero second timeout which results in immediate text rendering. If the requested font is not yet available, a fallback is used, and text is re-rendered later once the requested font becomes available.
  • I’ve assumed that Edge works the same as IE. I’ve also asked on Twitter to see if this assumption is correct.
  • Safari has no timeout behavior (or at least nothing beyond a baseline network timeout).

So, which one do we use?

Until browsers smooth out their differences or developers can take tighter control I’d say that solutions like Font Face Observer are still the best solution out there.

Links and resources

Cropping Images in CSS With object-fit

I’ve always struggled to get images to fit where I need them to without giving them explicit size in pixels that will only work on one screen size. Percentages are better but I’ve always struggled figure out what is the right percentage and whether it’ll look ok in smaller form factors.

With the object-fit property (and its partner object-position) we get very granular control on how an element responds to the size of its content box. Used by itself, object-fit allows for mage cropping and how it alters its size inside the containing box.

object-fit can take one of 5 values:

  • fill: this is the default value which stretches the image to fit the content box, regardless of its aspect-ratio.
  • contain: increases or decreases the size of the image to fill the box whilst preserving its aspect-ratio.
  • cover: the image will fill the height and width of its box, once again maintaining its aspect ratio but often cropping the image in the process.
  • none: image will ignore the height and width of the parent and retain its original size.
  • scale-down: the image will compare the difference between none and contain in order to find the smallest concrete object size.

The value that I use most often is contain to make sure that the image will fit its container. This is most useful in figures and similar containers where I do something like this:

figure {
  width: 100%;
}

figure img {
  object-fit: contain;
}

figure figcaption {
  width:max-width;
}

The idea here is that the figure element will take 100% of the width of its parent. You can also use object-position to move the image inside its container.

More information