QuirksBlog

Syndicate content
Updated: 5 hours 7 min ago

CSS and accessibility

Mon, 04/15/2019 - 3:28am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today’s topic is CSS and accessibility. I want to warn people for common accessibility pitfalls, but on the other hand want to do it in a sneaky, underhand way. In order to do so I need a list of common problems.

No chapter

I have decided that the book will not have a “CSS and accessibility” chapter because I suspect the people who need it most will skip it. Accessibility is “not realistic,” after all, and complicated, and nobody who’s blind visits our site anyway etc. You know the score.

Instead, my plan is to kind-of weave accessibility issues throughout the book, and treat them together with the technique they relate to. I am even going to try to avoid the word “accessibility” altogether, though I’m not yet certain I’ll succeed.

A list

When in doubt, make a list. What I’m currently looking for is a list of CSS/accessibiklity tips and tricks that will solve the most common 80% of the problems. That’s where you come in.

I am not certain if I’m going to treat ARIA. I have the feeling that if your HTML and CSS are structured correctly you don’t need any ARIA in 90% of the cases (but please correct me if I’m wrong). So complicated ARIA use cases fall outside the scope of this list.

With all that in mind, please give me your simple, easy-to-implement CSS and accessibility tips and tricks. I’ll add them to the list below, and I’ll write them into the book in a sneaky, underhand way. (I have no clue how that will actually work in practice, but it’s worth a try.)

The master CSS/accessibility list

The book is going to treat these topics:

  • Accessibility problems with changing the order of flex and grid boxes; what happens when source order is not visual order? (auto-flow: dense for grid; see also http://adrianroselli.com/2019/04/reading-order-bookmarklet.html for reading order bookmarklet)
  • Lack of contrast and how to solve it.
  • The position: absolute; left: -9999px class of solutions. (I am assuming these are safe as long as you apply them to the correct bits of content.)
  • Keyboard focus and :focus, :focus-within etc.
  • If it’s a button or a link, make it a button or a link. (Strictly speaking this is an HTML trick. But I’ll likely be able to squeeze it in somewhere.)
  • https://medium.com/@matuzo/writing-css-with-accessibility-in-mind-8514a0007939
  • Consequences of display: none; element taken out entirely.
  • Reduced motion, high-contrast, and similar media queries. (OK if they’re browser-specific)
  • How display: content can remove semantics http://adrianroselli.com/2018/02/tables-css-display-properties-and-aria.html
  • CSS symbol fonts or other icons may be read aloud (this may be beyond the scope of the book, since I won't treat fonts)
  • Difference between display: none, visibility: hidden, and opacity: 0.
  • Viewport height MQs (personally I'm not sure they're that great because of serious mobile issues with toolbars)
  • Prevent outline: none; we need those dotted outlines!
  • CSS-only disclosures such as dropdowns; usually not keyboard accessible
  • Sometimes JavaScript is more accessible than CSS. (Need practical examples; https://gomakethings.com/i-was-wrong-about-javascript-free-dropdowns/)
  • Modals. (Is this truly a CSS issue? Currently I see it more as a design issue.)
  • [Your CSS/accessibility issue here]

CSS book Table of Contents — draft 1

Mon, 04/08/2019 - 6:23am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today I present the first draft of the book’s table of contents for feedback — both on the topics, and on the chapter order.

h5,h5 + ul { margin-left: 2em; } Part 1: How CSS works
  • CSS Is (Not) A Programming Language
  • Imperative vs declarative languages
  • The CSS mental model
  • A style sheet as kind-of a JSON file: all commands are executed simultaneously. (Don't take this comparison too far)
  • CSS engines in the browser
  • layout vs appearance -> layout module vs paint module. Consequences for transitions -> use opacity and transform whenever possible
  • Formal syntax: rules, selectors, declarations, values. Semi-colon is REQUIRED.
  • CSS Is Global
  • CSS classes === JS objects (good comparison? take care). Multiple classes for 'OO'
  • Backward compatibility as a design principle. Drawback: past mistakes (box model; margin collapse) won't ever be fixed.
  • Vendor prefixes. History and purpose. Current status: don't use, unless you must.
Part 2: How to work with CSS
  • Test in several browsers; start with Chrome Win/Mac/Android, Firefox, Safari Mac/iOS, Samsung Internet, and one odd one, just to keep you on your toes.
    Ex: Fonts because a beginners mistake is to assume that browsers (oses) render fonts similarly and the space is consumed unequally, depending on input (asian characters, emojis,..).
  • Browsers are a reality to be experienced.
  • A WebSite Does Not Need To Look Exactly The Same In All Browsers.
  • Trial and error is OK.
  • Put borders around the elements you're working with. Makes it easier to see what's going on. More such tricks.
  • Better to be clear but verbose than succinct but incomprehensible -> shorthand properties
    • "Shorthands reset all components to their initial value, so you can avoid inheriting things you don't intend on.
    • Things like font (which *technically* isn't a shorthand) can avoid accidentally inheriting boldness or italicness, which is useful."
    • Exceptions: margin, padding, border, border-radius
  • If the answer is "add more divs", it’s the wrong answer - or the wrong question.
  • Please give me practical tips and tricks for this chapter.
Part 3: technical chapters Section 1: What makes CSS special

Selectors should have their own chapter. Not sure about the rest, though; maybe combine them into one.

Selectors
  • how selectors are read right-to-left
    Harry: I would never encourage anyone to write selectors *for* performance, but it just so happens that the traits of a ‘good’ selector also happen to make a selector very fast.
  • https://csswizardry.com/2015/04/cyclomatic-complexity-logic-in-css/
  • and how to write them well
  • pseudos
  • focus, :hover, :focus-within (Adrian)
  • CSS selectors can be very complicated giving one great satisfaction at one’s cleverness. Avoid the temptation to be clever. In 99% of circumstances use the dumbest selectors possible.
Cascade
  • How it works; purpose; drawbacks; using !important to identify problems
  • How to work out which CSS rules apply to an element, and why they do.
  • Example: style.display = ''; allows regular cascade to return
Inheritance
  • Too little for its own chapter? Combine with cascade or specificity?
  • Example: font inheritance good
  • Example: margin inheritance bad
  • Example: opacity inheritance confusing. Font-size may have similar problems
  • cascade VS. inheritance (Harry)
Specificity
  • Formal rules
  • How one selector overrides (or doesn't) another. How specific to make your selectors.
Section 2: CSS fundamentals Units
  • px, em, rem, vw/vh PERCENTAGES, nonsense units such as cm, pica, pt, in
  • Px fundamental CSS unit; em and rem relative to font size; vw/vh relative to viewport (which viewport; what if toolbars disappear?)
  • Keywords, global such as inherit, property-specific, and nonsense keywords such as initial and unset.
  • percentages: relative to WHAT?
Box model
  • width, height, margin, padding, border. Border-box. Percentages (or in Units chapter?)
  • border vs outline
  • Mistakes were made: box model, margin collapse
  • Block-level vs inline
  • display (inline, block, grid, flex)
  • display is secretly display-inside (grid, flex) and display-outside (block, inline, table-*)
    td {display: flex} -> td is not a table cell any more; https://www.smashingmagazine.com/2019/04/display-two-value/
  • vertical aligmnent
  • Line boxes? (Here or elsewhere?) Be brief.
Layout
  • Flexbox and grid
  • More fundamental stuff? If so, what?
  • Old techniques: floats and tables. Do not use. Distrust any resource that tells you to use floats.
  • flexbox order isn't reflected in the accessibility tree
  • reordering consequences and options in css
Positioning and z-index
  • Positioning basics
  • Stacking contexts
  • * {position: relative} <- why not?
Special HTML elements
  • inputs
  • scrollbars
  • <progress>, <details>, <meter>, and <hr> are harder than they should be.
  • Table elements have their gotchas.
Advanced thingies
  • Better title needed
  • variables/custom properties: Highlight local scoping possibilities
  • calc()
  • Advanced math stuff (max() and so on) Ask Tab again in December.
  • Enough for separate chapter? Split up?
Section 3: Other topics

These are the most sketchy chapters.

Viewports
  • ? Mostly because I'm the worldwide specialist and writing this chapter would be easy. Not 100% certain it belongs in a beginners handbook, though.
  • Visual viewport, layout viewport, meta viewport.
  • Why so complicated? What problem does it solve?
Media queries and @supports
  • Especially width (and warning not to use device-width)
  • The limits of @supports (transition-property: nonsense)
CSSOM
  • Explanation.
  • Dangers of offsetWidth and related -> re-layout
  • How JavaScript can change styles and style sheets
  • Typed Opject Model https://css-tricks.com/working-with-the-new-css-typed-object-model/
Modularization
  • Not sure yet if I should include this chapter.
  • Inline CSS and why it's generally bad
  • CSS modules
  • Ordering your stylesheet http://bradfrost.com/blog/post/css-architecture-for-design-systems/
  • BEM
  • CSS in JS

In search of the Miui Browser

Thu, 04/04/2019 - 5:14am

Today it’s time for an old-fashioned browser detective story about the Miui Browser, the current state of non-Google Chromia on Android, and assumptions about browsers and UA strings. In addition, this article will highlight a few principles of mobile browser research, one of which was vindicated rather nicely.

Update: severe vulnerability discovered in Miui/Mint Browser.

The old gang

A client wants me to see how the the old gang of non-Google Chromium browsers on Android is doing. We all know Samsung Internet is doing fine, thanks so much for asking. But what about the others? Several of them, such as HTC Chromium, have silently disappeared. What’s the exact current score? Who are the survivors?

When in doubt, tweet. I asked my followers for non-Google Chromium browsers, and enough of them responded to get a first impression. Samsung Internet, obviously, but also the Miui Browser for Xiaomi devices, using mostly Chromium 61, but sometimes 63. That was interesting.

The device

In order to say anything useful about such a browser, you need the device it’s made for — even though it may be available for download, as is the case for the Miui Browser. I needed a Xiaomi phone. (This, by the way, is the principle that was vindicated. We’ll get to that in due time.)

So I went to the local friendly phone shop and ordered a RedMi 5, a model that was present in several browser strings my followers sent me. (And why didn’t I order it online? Because such small shops allow you to test phones before buying them, so that I can be certain they contain the browser I want. The shop going out of business would be bad for my business. So I ordered the device there and allowed them to take their margin.)

The home screen

I did this on Thursday, and picked up the phone on Friday afternoon, politely declining their testing offer (I was tired, and the end of the week was very near). I only got around to firing it up on Tuesday. And when I did ... deception! There was just a regular boring old Google Chrome on the home screen!

Mistake #1 on my side: I plain missed the “Browser” icon in the upper left.

In my defense, this default home screen is non-standard. In fact, it’s the first time I see this particular configuration of icons.

I expected the “Browser” icon to be in the favourite bar at the bottom of the screen, in the exact spot the Chrome icon takes up. That’s the proper place for the browser that the vendor wants its users to use. If Google Chrome is there, it means the device vendor has no browser of its own. (Or that the operator put it there, but this phone was unlocked, so there’s no operator hanky-panky going on.)

I lamented the fate that made me throw away hundreds of euros on a worthless device, dutifully noted that the default browser was a Chrome 67, which after an update became a 73, yawned widely, and put the RedMi away. No Xiaomi Chromium for me or my client.

The WebView

Later that day I hit on what I thought was mistake #2. I re-checked the browser strings my followers had sent me, and sure enough, there it was, in every single browser string I received: the telltale Version/4.0 that denotes a WebView.

A WebView is a secondary browser on a mobile device that is available for apps such as Twitter and Facebook. Clicking on a link in those apps opens web pages not in the device browser, but in the device WebView. That way the users don’t have to leave the app. Engagement stuff.

On iOS you are not allowed to install other rendering and JavaScript engines. Therefore, browsers such as Chrome and Firefox iOS are not in fact Chrome or Firefox. They use the Safari WebView for their actual browsing.

On Android you can install any browser you want, but Google requires all device vendors to use the Google WebView. It is updated regularly and is at most one or two versions behind Google Chrome.

I assumed these Xiaomi users had seen my tweet in their Twitter app and clicked on the link, firing up the system WebView. It was a bit odd that all these devices used Chromium 61 instead of the expected 71 or 72 — but apparently Chinese manufacturers did not have to worry about that rule as much. Or something.

I thought I had found my mistake. In fact, I hadn’t. In fact, I’d done exactly the right thing by buying the device and ignoring the Version/4.0. But I didn’t know that yet.

Browser

On Wednesday I felt bad for my client, whom I’d promised a Xiaomi Chromium that I couldn’t deliver. So I decided to check in on the one definite non-Google Chromium: Samsung Internet. Samsung claims you can install that browser on pretty much any Android device nowadays. Let’s put that to the test and install it on the RedMi 5.

Play Store, install, no hitch, done. Load test site, works. “Make Samsung Internet your default browser?” Since I was feeling vengeful and spiteful towards Google Chrome, I decided to do it. The phone sent me to a settings menu where I could select my default browser. (Incidentally, I like this idea. Instead of allowing browsers to set themselves as the default, merely allow them to open the system setting for the default browser. This might even be a solution to the latest Google-EU conundrum.)

Anyway, the menu gave me the options for my default browser: Google Chrome, Samsung Internet ... or “Browser.”

“Browser?”

Wait a minute. There IS a vendor browser on the RedMi 5! Called Browser. (Browser and Internet are the only two names allowed for a vendor browser in Asian mythology. Don’t ask me why.)

I finally noticed the icon on the homescreen, tapped it, saw an unknown browser open before my very eyes, sent it to my test site with trembling fingers, and lo and behold, there was MiuiBrowser 10.1.2 in all its glory:

Mozilla/5.0 (Linux; U; Android 8.1.0; en-gb; Redmi Note 5 Build/OPM1.171019.011) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.128 Mobile Safari/537.36 XiaoMi/MiuiBrowser/10.1.2

Another surviving member of the old gang! I hadn’t wasted my client’s time and my money after all! Good days and weird browsers are here again! I was in paradise.

Then I noticed the snake: Version/4.0. A WebView.

Again the WebView

What was this? Why was this application that was clearly a browser pretending to be a WebView?

One possible answer is that it’s in fact only a skinny app that uses the WebView for all its actual browsing. I saw that before in the curious case of the Indian Micromax.

I didn’t believe this was a skinny app, though. My gut feeling told me that this is a real browser. So I downloaded an app that tests the WebView, and it gave me this for the WebView UA String on the RedMi 5:

Mozilla/5.0 (Linux; Android 8.1.0; Redmi Note 5 Build/OPM1.171019.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/73.0.3683.90 Mobile Safari/537.36

That sounds about right. It’s a Chromium 73, which fits, because I just updated the device. It has the crucial wv bit in the Android/device part of the string, which denotes a WebView.

Version/4.0 and wv

So Miui is a true browser, and not a WebView. But why does the Miui Browser incorporate Version/4.0 in its browser string?

I don’t know the answer. Maybe it wants to end up on the right side of browser detects written by clueless web developers? Maybe they just plain forgot to change it? (For a short while early in its history, Chrome’s navigator.vendor was “Apple.” They obviously forgot to change that field. A scenario like this is not impossible for Miui.)

In any case, Version/4.0 no longer necessarily denotes a WebView, though I think wv still does. So we’ll have to use that last substring to identify WebViews from now on. Duly noted.

Market share

We have now positively identified the Miui Browser as the Chromium-based system default browser on the Xiaomi RedMi 5, and likely other models as well.

The first question any web developer will ask is: OK, what’s its market share?

I don’t know. There’s only one source for this sort of data, StatCounter’s global statistics, and it doesn’t count Miui Browser as a separate browser. Miui’s stats are part of the general Google Chrome stats.

StatCounter counts Samsung Internet as a separate browser, but only after the entire Samsung Internet team threatened to holds its collective breath for days on end. Apparently nobody issued a similar threat for the Miui Browser. So we have no data.

I may be able to find data from a different source, though. Let’s see what happens. But even if that succeeds I would be hugely surprised if Miui Browser holds more than 1-2% of the mobile browser market.

Zoom reflow

If talking about market share yields nothing useful, let’s talk about features instead. Is the Miui Browser browser different from a regular Google Chrome 61?

Normal zooming: you only see part of the line.

Miui zooming: the lines reflow to fit on the screen.

Yes, it most definitely is. Miui Browser supports zoom reflow, one of my absolute favourite mobile browser features, and one that Google Chrome never supported.

If a user zooms in to a visual viewport size where lines of text do not fit on screen, most browsers do nothing. The lines go off-screen, and if users want to read them they’ll have to pan left or right. Safari, Chrome, Firefox, Samsung Internet, and most other mobile browsers work like that.

Miui Browser and Opera Mobile, however, support zoom reflow. If the user zooms in to where lines of text do not fit on screen, the browser reacts by shortening these lines, so that the text stll fits. This does wonders for readability, especially with those annoying sites that have far too long lines.

Zoom reflow has a down side as well: the browser has to recalculate the layout of most of the page. Elements may suddenly contain many more lines of text, and therefore grow in height. Other elements below the affected elements will be moved downward, even if their height isn’t adjusted. This causes massive reflows and recalculations of the layout. Worse, if the user zooms out the entire process has to run in reverse.

Despite this, the presence of zoom reflow is enough to make me consider switching devices in order to have the Miui Browser available. I simply LOVE it. (OK, Opera Mobile supports it as well.)

Variants

Christian Schaefer pointed out the Miui Browser can also be downloaded. Would that yield the same browser as the one on the device?

Christian referred me to the APK Mirror site (a site so horrible that I refuse to link to it, although it does appear to be trustworthy). At first I didn’t want to mess with a complicated site, so I just searched the Play Store for “Miui Browser” and got a hit. Download, install, try. This is the browser:

Mozilla/5.0 (Linux; U; Android 5.0.1; en-gb; GT-I9505 Build/LRX22C) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.128 Mobile Safari/537.36 XiaoMi/Mint Browser/1.6.2

There are two important differences with the pure Miui on the RedMi: it’s a different device (Galaxy S4, because it happend to be within reach of my hands), and the name is not Miui Browser but Mint Browser, though it’s still branded Xiaomi. Also, the Version/4.0 is very much present in this browser, which is downloaded and thus certainly not a WebView.

But is there an actual difference in features? Yup, of course there is. Mint Browser does not support zoom reflow, instead handling zooming exactly as the other, boring browsers.

That leads to the question if the Mint Browser is truly a Miui Browser, or just a downloadable variant. I’m currently assuming the latter, and have concluded that testing on Mint Browser cannot stand in for testing on Miui Browser.

Then I gritted my teeth, steeled my soul, and dove deep into APK Mirror and its terrible process flow. It took me twenty minutes to figure out how to download something, and I could only do that because I browsed the site on Chrome Mac, then copied the correct clicks to my phone. It was an awful experience — but I heroically snatched Miui Browser 10.6 from the claws of this site:

Mozilla/5.0 (Linux; U; Android 8.0.0; en-gb; SM-G930F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/61.0.3163.128 Mobile Safari/537.36 XiaoMi/MiuiBrowser/10.6.1

This one is now on my Galaxy S7, hence the different device string. It’s a later version than the one on the RedMi 5, though it still uses Chromium 61. But the browser name is Miui Browser, and not Mint Browser. Also, it supports zoom reflow. That’s enough for a positive identification. The APK Mirror version is a true Miui Browser.

Conclusion: non-Google Chromia

I have now identified Miui Browser as one of the few surviving non-Google Chromium browsers on Android, in addition to Samsung Internet.

Update: severe vulnerability discovered in Miui/Mint Browser.

Also, I feel vindicated by my insistence on buying an actual device. If I’d just searched on the Play Store I would have got the Mint Browser, which is not the native browser on Xiaomi devices. Now I’ve got the real thing. Also, I could experimentally verify that the APK Mirror download actually is the real thing as well.

It’s interesting that, like Samsung, Xiaomi thinks it’s useful to offer its browser for download. Also, Miui Browser is not restricted to Xiaomi phones any more, just as Samsung Internet is not restricted to Samsung phones any more. I now have a Xiaomi phone with Samsung Internet, and a Samsung phone with Miui Browser. Interoperability FTW!

It appears Samsung’s web developer communication strategy is partly being copied — and that shouldn’t come as a surprise, since it’s a pretty successful one. Web developers are aware of the existence of Samsung Internet, and can download it for testing even on non-Samsung devices. If Xiaomi made the downloading process easier, and did something about web developer outreach, it could have similar success.

That leaves two minor mysteries to be solved: its market share, and its use of Version/4.0 in the UA string of a true browser. I hope to be able to offer new insights later.

For now, though, I will continue my search for other surviving non-Google Chromia. If you think you’ve discovered one, please go here, add a note as to the device or the browser, and hit Send Info. The Internetz will thank you later.

Google to offer Android users browser choice

Thu, 03/21/2019 - 5:17am

Yesterday the European Commission fined Google for almost €1.5 billion for unfairly favoring some of its online advertising services over those of its rivals — and it appears the EC isn’t done yet.

One of the ongoing antitrust cases is about Android, and more specifically about Google Services, the package of Google apps such as Play, YouTube, and Chrome that Android-using hardware vendors must either adopt completely, or not at all.

Getting Google Play on their devices requires vendors to adopt Services. That is the reason that almost all non-Chinese Android phones come with Google Chrome installed, even if they have another browser, such as Samsung Internet, on the home screen.

Browser choice

If Google Services is ruled in contravention of EU antitrust rules, that may have an impact on the Android browser market. Google itself sees that as well, and is taking measures. Yesterday, it stated in a press release:

Now we’ll also do more to ensure that Android phone owners know about the wide choice of browsers and search engines available to download to their phones. This will involve asking users of existing and new Android devices in Europe which browser and search apps they would like to use.

(Haven’t we heard this before? Indeed.)

Apparently, the European Commission wants Google to clarify that users can download other browsers. Although this is a good idea when it comes to diversifying the browser market, there are several knotty problems that I don’t see an easy solution for.

To be fair to Google, Android has always allowed consumers to install any browser they like, and using any browser they can access any search engine they like. (So could Windows users, back in the day.)

Also, the average consumer doesn’t care about browsers. On Samsung devices some users (about 30-40%?) use Samsung Internet over Google Chrome, but that’s only because Samsung Internet is on the home screen and Google Chrome is not.

Browser choice screens

Still, it seems European Android users will get a browser choice screen similar to what we saw ten years ago.

We only have to make the old choice screen responsive, and it’s ready for roll-out. That responsive bit is important: the browser that ends up at the top of the list will likely be selected far more often than the others. Most consumers don’t really care about the choice they’re being given, and a tap is easier than a scroll and tap. Therefore, a random order of browsers seems likely, just like ten years ago.

But which browsers will be selected for the browser screen? Ten years ago it was clear: IE, Firefox, Chrome, Safari, and Opera.

Right now the situation is much less clear. Let’s see:

  • Google Chrome, Opera Mobile, Samsung Internet, and Firefox should be on the list for sure.
  • Any other vendor-created Chromium browser? I’m not sure which ones there are right now, and they’ll likely be restricted to the devices of their vendor, but as long as we’re being inclusive they should be on the list where possible.
  • UC? Yes in principle, but it’s a bit odd for Europeans, who’ve never heard of it.
  • QQ, or however the TenCent browser is called nowadays? Same problem.
  • Opera Mini? The average consumer has no idea what a proxy browser is and will get confused. (The average web developer hasn’t, either, and will, too.)
  • Puffin? Too weird.

Besides, who’ll take the decision which browsers to include? Google, most likely, though it is restrained by the EC’s cold staring antitrust eyes in its back. Then again, the EC doesn’t know anything about browsers.

And what if the device’s browser is already something other than Google Chrome? In theory the choice screen would not be necessary there. (Ten years ago Microsoft only offered the choice screen on new computers. But Google explicitly said “existing and new Android devices.”)

And what about WebViews? Here Google’s monopoly is even bigger than with the Google Chrome browser, since there is no choice whatsoever under the Google Services agreement. An extra browser, sure, that’s allowed. A new WebView is not: you must use the Google-provided Chrome.

So there are plenty of detail questions that I dont’t know the answer to. Worse, I’m suspecting Google and the EC don’t, either.

The result

What will the result be? As far as I can recall, when Microsoft offered users a choice ten years ago, not all that much changed in the browser market. Still, we have to consider the possibility of a minor mobile browser market shake-up in Europe.

So let’s make a note of the February 2019 mobile browser market in Europe according to StatCounter:

  1. Google Chrome: 59.7%
  2. Safari iOS: 26.2%
  3. Samsung Internet: 10.3%
  4. Other: 3.8%

Let’s revisit this in a while and see if anything has changed. Google wasn’t very clear on when the choice screen would be offered, but I expect it to be somewhere in the next year or so.

But I am not expecting a lot from this initiative — and I suspect that’s exactly why Google is offering it. Still, this episode serves to highlight that dominance in the browser market has now passed to Chrome, and that from a diversity point of view it would be a good idea to do something about that.

The elephant in the room

Finally, we’re left with one elephant in the room: iOS. Contrary to Android, iOS does not allow the installation of other rendering engines. Isn’t that a much worse monopoly than the one Google has over Android? Shouldn’t Apple, too, be forced to give consumers choice?

Scope in CSS

Tue, 03/19/2019 - 2:53am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today we treat the knotty problem of CSS selector scope. JavaScripters rightly feel that the fact that all CSS selectors are in the global scope complicates their applications. What can we do about it?

I wrote the explainer below. As usual, I’d love to hear if this explainer works for you or confuses you.

Global scope

Any CSS selector is valid throughout the document. If you use p span it selects any span in a p in the entire document. Here, every span in a p in the document has a red background.

p span { background-color: red; }

Sometimes you don’t want that. Sometimes you want to select only spans in ps in your specific module. This is the core of the scope problem in CSS: how to restrict your style definitions to only the module you’re working on.

The fundamental solution is adding a class name or ID before the actual selector; something like #myModule p span. Now the declaration is scoped to the myModule element.

In this code example, spans in ps are red, except when they’re in the myModule element; then they’re blue.

#myModule { border: 1px solid black; padding: 1em; } p span { background-color: red; } #myModule p span { background-color: blue; }

Yes, scoping sort-of works, but your CSS file becomes a jumbled mess of selectors, overrules, and other stuff. For intance, where exactly do you put the #myModule p span rule? I always place it after the global selector it overrules, as in the example above, but I can see why people would set it straight after #myModule. Fun times ahead when you’re taking over someone else’s CSS.

Scoping CSS selectors with sane, readable syntax is one of the purposes of the many CSS-in-JS solutions that are now vying for developer attention. (Another purpose is making sure that scoping IDs aren’t repeated — if your HTML contains two elements with id="myModule" you have the same scoping problem all over again.)

However, it appears that the CSS scoping problem will be solved in the not-too-distant future. A limited local scope is already present, and a full solution is in the making.

CSS custom properties

CSS custom properties (also called CSS variables) already have scope. It is possible to redefine the value of a custom property for a specific element and its descendants.

Take this example:

body { --color: red; } #myModule { border: 1px solid black; padding: 1em; --color: blue } p span { background-color: var(--color); }

Now a span in a p has a red background, except in myModule, where it has a blue background. In practice, the html and body elements count as the global scope; most other elements as a local scope.

Custom properties can hold any valid CSS value, and they work for any declaration. So we could extend the example like this:

body { --color: red; --spandisplay: inline; } #myModule { border: 1px solid black; padding: 1em; --color: blue --spandisplay: block; } p span { background-color: var(--color); display: var(--spandisplay); }

Now spans in ps in myModule have display: block, while spans in ps elsewhere have display: inline.

There is no doubt that true local scope has landed in CSS with the addition of custom properties. There is also no doubt that the system can be clunky when you want to use local scoping on a massive scale.

In theory it’s possible to define a gazillion custom properties in myModule for internal use, and define the same properties with different values in otherModule. However, this assumes that, internally, the modules will have the same structure. For instance, the simple example above assumes that every module in the entire page uses p span in a similar way. If otherModule would use p strong instead, you’d have to add new declarations. All this is not impossible, but it’s questionable whether it solves CSS’s scoping problem in an easy-to-use way.

So all in all the verdict is mixed. Yes, custom properties bring local scope to CSS, but it’s best used in small, subtle ways instead of the wholesale, system-wide way JavaScripters would like to see. [Unless I’m missing something here. If I do, please tell me. I need to know.]

CSS nesting

The CSS Nesting specification offers a new way of sort-of creating sort-of local CSS selectors. Note that this spec is relatively new, and it will take a little while before browsers support it.

CSS preprocessors have done nesting for ages now, and the proposed syntax is quite close to SASS:

p span { background-color: red; /* display: inline is the default anyway; no need to define it */ } #myModule { border: 1px solid black; padding: 1em; & p span { background-color: blue; display: block; } }

The & p span evaluates to #myModule p span; in other words, the & adds the parent selector. Note that the & is required: CSS needs to know where to insert the parent selector.

On the one hand, CSS Nesting offers syntactic sugar, but nothing fundamentally new. We already saw how to write the example above in today’s CSS:

On the other hand, the nested variant is much more readable, and offers you a simple way of stating whether a certain selector is local or global. It is totally clear that & p span is a local selector, and that its styles will not apply outside myModule. The p span outside the block, on the other hand, is clearly global.

This makes it a lot easier to see the scope of your selectors at a glance, and to subdivide your CSS files. If you’re working on myModule, you add styles to the myModule block. If you define styles outside that block, it’s clear that they are global.

Would CSS nesting help?

Today’s question to JavaScripters is: do you think that CSS Nesting will make your work significantly easier? It seems so to me, but I am an old-guard front-end developer with little knowledge of the modern JavaScript ecosystems, so I might miss something.

if statements and for loops in CSS

Wed, 03/13/2019 - 4:12am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today I continue to look at CSS as a programming language. The question whether it is one or not is a very hot topic right now, but I’m not terribly interested in the answer.

Instead, I’d like to know if describing certain CSS structures in programming terms helps you learn CSS better or quicker, or if it hinders you. In other words, is there any educational value in treating CSS as a programming language?

Please tell me if the explanation below is helpful or confusing to you.

if statements

An area where the CSS programming language is less developed than JavaScript is control structures — or so it would seem.

Still, CSS has if statements. Here are a few examples:

@media all and (max-width: 900px) { } @supports (display: flex) { }

These mean “if the layout viewport is at most 900px wide” and “if the CSS engine accepts display: flex.” There is no doubt that these are actual if statements: the code blocks are only applied if the condition is true. (Also, the specification for @media and @supports is called CSS Conditional Rules. That’s a dead giveaway: at-rules are meant to be if statements.)

But let’s take a look at a — dare I say it? — more iffy example. Is the following also an if statement?

menu a { color: red; }

“If there is a link within a menu, make it red.” Several people I interviewed for the book were passionate in their belief that selectors are if statements as well.

Do you agree? Do I agree? I’m not sure, although I do see the point: it is possible to see selectors as such. Whether you consider them true if statements probably depends on your definition of an if statement.

for loops

Let’s make things slightly more complicated by considering for loops. Now at first sight it would appear CSS doesn’t have any. Still, what about the same bit of code we saw above?

menu a { color: red; }

In a way, a selector like the one above could be considered a primitive for-loop. The browser is told to loop through all <a> elements inside a <menu> element and apply a red colour.

Is a selector a for loop? Can it even be an if statement and for loop at the same time? Again, this depends on your definitions of for loops and if statements.

I’d like to mention in passing that it is possible to add extra logic to CSS for loops.

menu a:first-child { color: blue; } menu a:not(#current) { color: red; }

These extra selectors can be treated as if statements within a for loop: go through all links in a menu, but skip this one and give that one special treatment.

Declarative vs imperative

Let’s take the most expansive view and say that CSS selectors can be considered both if statements and for loops. That will sound fairly weird for anyone with a background in JavaScript, since these two types of control structures are simply not the same. So how can you replace both by a single structure?

Here, I think, we once again see that CSS is a declarative language, and not an imperative one. In declarative languages some simple control structures can be expressed much more succinctly than in imperative ones.

Take the last code example above. In JavaScript we’d have to say something like:

for (all menus) { for (all links in this menu) { let first = [figure out if this is the first link in the menu] if (first) { link.color = 'blue' } else if (link.id !== 'current') { link.color = 'red'; } } }

The drawback of the JavaScript version is that it’s more verbose than the CSS version, and hence more prone to error. The advantage is that it offers much finer control than CSS. In CSS, we’ve just about reached the limits of what we can express. We could add a lot more logic to the JavaScript version, if we wish.

In CSS, we tell the browser how links should look. In JavaScript, we describe the algorithm for figuring out how an individual link should look. Neither is wrong, but in this example the CSS way is the more efficient way.

Personally, I’m fine with seeing CSS selectors as if statements and for loops at the same time. However, I feel that once you start understanding CSS, the fact that selectors are ifs/fors becomes less and less relevant. Instead, selectors are just selectors: great for relatively simple declarations; less so for very complex ones.

Helpful or confusing?

If you’re a JavaScripter who’d like to get to know CSS better I’d love to hear if the few examples above are helping or confusing you. The more feedback I get, the better I can write a book that helps you learn CSS instead of just confusing you.

Thanks.

Feedback

Badly formatted

See also https://csswizardry.com/2015/04/cyclomatic-complexity-logic-in-css/

See also https://adactio.com/journal/14574

I did a presentation about this topic at AmsterdamJS, and the feedback I got made me conclude that this approach is not really suited for learning CSS. Everybody understood my point, but most thought it didn't really help them understand CSS better. So this is going to become a sidebar in the book, and not main text.

Algorithms in CSS

Tue, 03/05/2019 - 7:02am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today we’ll discuss the writing of CSS algorithms, inspired by Lara Schenck’s excellent article on that topic, which states that not only CSS is a programming language, but you can write algorithms in it.

What follows are my words; not hers — I have different points to make, and give different examples. If you want to hear Lara’s own words on CSS algorithms, drop by at CSS Day, 13th and 14th of June, Amsterdam, where she will speak.

CSS as a programming language

Is CSS a programming language? That's a hard question. In a Twitter poll I conducted in February 2019, 47% of the 3,000 or so participants said that CSS is a prorgamming language, while 53% said it is not.

So there’s no agreement on this — it all depends on your definition of a programming language. If a programming language must be imperative, then no, CSS isn't. If a programming language is anything that gives computers instructions to do anything, then yes, CSS is.

But there’s a more important question: does it matter? Does the fact that CSS is, or is not, a programming language make it easier for you to learn? Let’s discuss CSS algorithm design, which presupposes CSS is in fact a programming language, and see if it helps.

Algorithms in CSS

Saying you write algorithms in CSS is a psychological trick that can put you, and, more importantly, your co-workers, in the right frame of mind for approaching tricky CSS problems.

You should think before you start coding; that’s just as true in CSS as it is in JavaScript. If, for instance, you need a certain layout it is worthwhile to make a quick sketch and decide on your overall approach. Will you use grid, flexbox, floats, or even absolute positioning? (The last two options are not really recommended, by the way.) Will you mix approaches; for instance grid for the overall layout, but flexbox for the naviation bar?

Thinking about these issues before you start coding will save you a lot of work in the long run, just like thinking about the structure of your JavaScript app before you write it helps you create it more quickly.

Now if you slap the name “algorithm design” on this process you achieve several goals. You are able to explain to programmers why you’re doodling boxes in boxes while making cryptic notes about grid gaps and flex bases. You invite those that are new to CSS to share your exploration of a layout problem, and can quickly introduce them to the pros and cons of grids and flexbox. (And remember: the best way to really learn something is to explain it to someone else.)

Naming things

Most importantly, naming things gives you power over them: if a bunch of disconnected doodles and notes become an algorithm design, you grant them the much higher status of a computer problem. And engineers exist to solve tricky computer problems, don’t they? Here, let me show you why I think flexbox is the right approach in this situation ... and before you know it your co-workers will become as engrossed as you are in the details of this exciting new algorithm.

Once the doodling-and-thinking phase that we now call algorithm design is over, you should whip up some proof-of-concept code (it’s OK if it’s ugly), show that your approach will work (or that it won’t, which is also useful data), then test your ugly code in several contexts, and finally iterate until the code is cleaner and more understandable to others.

You’re doing just the same as when you would write a tricky JavaScript module, in other words. Go from design via prototyping and testing to optimsation — and the fact that you use a different programming language doesn’t matter. Meanwhile the magic word “algorithm” will make sure that everyone understands you’re doing some real programming here.

Cool, huh? The power names have!

The CSS mental model

Tue, 02/26/2019 - 5:35am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters. This series of article snippets are a sort of try-out — pre-drafts I’d like to get feedback on in order to figure out if I’m on the right track.

Today we will attempt to describe the different mental models for CSS and JavaScript. Everybody agrees there is a difference, but nobody’s able to define exactly what that difference is. So let’s try.

(Also, at the last moment I switched from describing CSS as “context-based” to “state-based.” I hope that makes more sense, and it’s one of the points I’d like feedback on.)

CSS and JavaScript mental models

Programming CSS requires a different mental model than programming JavaScript. CSS is a declarative language, while JavaScript is an imperative language. (Also, it’s an open question whether CSS is a programming language at all. We’ll get back to that later, but for now we’ll pretend it is.)

Those who have experience with declarative languages such as Prolog, or even spreadsheets, will have the advantage over people who only know imperative languages, who may be confused by CSS at first, since it lacks many of the control structures they’re used to in JavaScript.

The differences go deeper, though. Fundamentally, JavaScript execution is time-based. That is, everything happens in the order prescribed by the program. There is a time, at the very start of execution, that a certain variable does not exist yet. Then it’s defined and assigned a value, and later that value is changed, and so on. An if-statement based on that variable will have different outcomes at different times.

Not so CSS. All CSS declarations get their value at the same time, and they all take effect at the same time. It is impossible for any CSS declaration to be applied earlier than any other CSS declaration. Declaration order matters, but any conflict is resolved immediately and doesn’t require (or even allow) control structures. The same CSS will always give the same result.

State-driven change

[Could I even say “state-based programming?”]

CSS does accept changes to the initial rendering of the page, but it is fundamentally state-driven. It can only react to a limited number of well-defined state changes in a web page. A good example is changing a background color on hover. nav a:hover { background-color: red; }

When the link’s state changes (i.e. the mouse pointer hovers over it), CSS switches from one set of instructions to the other, and when the state changes back to no-hover, CSS switches back to the original instruction set.

You can achieve the same effect with a few lines of JavaScript, but it’s instructive to study the differences. el.onmouseover = function () { this.style.backgroundColor = 'red' } el.onmouseout = function () { this.style.backgroundColor = ''; }

First, something that’s so obvious that it’s hardly ever mentioned: JavaScript needs CSS in order to actually change the background color. It is impossible to do this in any other way. Conversely, the CSS declaration does not need JavaScript. When it comes to styling, CSS is more fundamental than JavaScript - closer to how browsers actually work, and thus much faster.

Next, JavaScript needs two statements instead of CSS’s one. It does not detect a state change automatically, as CSS does. Instead, you have to take it by the hand and guide it through all possible options, and make sure it notices not only the state change, but also the change back.

Then, JavaScript needs an extra control structure to make sure that the state change is detected on all links in the navigation instead of just one. This is not particularly difficult, but it needs to be done. Again, with its single selector CSS is more elegant.

Still, JavaScript has its advantages as well. Unlike CSS, JavaScript allows you to cancel the background change by adding an if-statement to determine whether the link background change should take place. In CSS you defined the styles to be applied in a state of hover, and those instructions are always followed. If you want more fine-grained control, JavaScript is the better solution.

Elegance vs control

More fine-grained control is not an end in itself. It all depends on the context. Sometimes, like in the background example, the simple, elegant, fast solution is better. In more advanced situations there comes a time when JavaScript, with its fine-grained control, becomes the better answer.

Keith Grant pointed out an interesting analogy. If we as humans wish to run, we just tell our body to run, and it obeys. We could deconstruct the act of running into its constituent parts like “raise left knee,” “raise left foot,” “advance left leg,” and so on, but that is much harder to do and we’d likely fall over, as this game shows.

In this analogy, the run command would be CSS, and the detailed foot-and-leg instructions would be JavaScript. The analogy is flawed, as all are, since as humans we’ll almost never operate in a context that requires us to deconstruct the act of running, while a web page might benefit from deconstructing the act of changing background colors. Still, the analogy might help you to understand the advantages of the CSS mental model better.

It doesn’t answer the most important question, though. When do we cross the line? When does JavaScript become the better option? In the end, that depends on your context, both the project you’re working on and your familiarity with CSS and JavaScript. Still, I have the feeling that JavaScripters who are unfamiliar with CSS tend to draw the line too early, and that their simpler use cases might be better served by a pure CSS solution. The choice is yours

So the choice is yours. Elegant, but limited, state-driven simplicity versus controlled, but complicated, time-based execution. There is no right or wrong here — just a careful weighting of options and contexts.

Whatever you choose for a particular project, if you work with browsers you should have a basic understanding of both approaches. And if you want to master CSS you need to understand state-based programming and the mental model that goes with it.

Feedback

Badly formatted

https://twitter.com/ptrdo/status/1100425471802585088
This is a very good approach. Perhaps another aspect of declarative v imperative (assumed but not mentioned) is how declarative rule-setting defines characteristics which can be universal and prescribed without the elements needing to exist, while imperative expects an instance.

https://twitter.com/tabatkins/status/1100421543144841216
The bit about "needing an extra control structure" could use some slight expansion. You need a loop over all links inside of nav (itself probably obtained with a selector), then a mutation observer to *add* the listeners for new links and *remove* them if the link is moved.

State machines: https://medium.com/@DavidKPiano/css-animations-with-finite-state-machines-7d596bb2914a

https://adactio.com/links/14866
I’m not sure if I agree with describing CSS as being state-based. The example that illustrates this—a :hover style—feels like an exception rather than a typical example of CSS.

https://twitter.com/leifastrand/status/1100801652586659843
Declarative = you describe the intended outcome. Imperative = you describe the steps to take. JS devs often encounter something similar: use map, filter and reduce over a collection to define intended result, or imperatively define the steps to take as a for loop.

Mail
JS is verbs, CSS is nouns.

CSS for JavaScripters 1

Tue, 01/08/2019 - 5:17am

I am likely going to write a “CSS for JavaScripters” book, and therefore I need to figure out how to explain CSS to JavaScripters.

Below I take a stab at explaining CSS files as JSON files. What I’d like to know from you is if this comparison makes sense.

If you’re a JavaScripter who’d like to learn some more CSS, please tell me if this helps you understand CSS better or not, and what could be improved. I’d be grateful for your feedback.

If this article generates useful feedback I might do it again. What better way to figure out if you’re making sense than to actually ask the target audience?

CSS as JSON

Suppose your job is to revise a JSON file. This file is sent on to a module that produces a web page. This web page should be changed, and for Reasons the only way to do that is by revising the JSON. You do not have access to the module’s source code, but you have incomplete documentation.

Since JSON is declarative, the order of declarations/properties does not matter. Something like "heroImage": "/images/pngs/hero2.png" can occur anywhere. It’s clear that this property defines the hero image to be shown on the web page, and its exact position in the JSON file does not matter.

Suppose the JSON contains the following:

{ [...], "heroImage": "/images/pngs/hero2.png", "heroImage": "/images/pngs/hero3.png", }

Which hero image will be shown? hero3.png, obviously. The second use of "heroImage" overwrites the first one.

Other properties are much broader and vaguer in their usage. Suppose you find "layout": "sidebar" in the JSON, and you read in the documentation that the values "main" and "footer" are also allowed. The documentation does not make very clear what these values do, so you’re forced to experiment: just change the value of "layout" and see what happens.

There are many more properties like this, that range widely in their effects and aren’t always very clearly documented. The only way to start understanding their purpose is to just try them.

And what if you add "lyout" : "sidebar" to the JSON? Your expected layout won’t materialise — but there’s no error message to alert you to the fact that you’ve made a syntax error. JSON files don’t do error messages — unless the entire file is invalid. That’s not the case here: "lyout" : "sidebar" is perfectly valid JSON. You’ll have to spot the typo by yourself.

This situation resembles web developers creating or revising CSS files. Like JSON files, CSS files are not programs. but a series of declarations that programs use in order to create output. Also, they fail silently when they contain instructions that the receiving program does not understand.

If you approach CSS as you approach JSON you’ve taken a step toward understanding it.

©2003 - Present Akamai Design & Development.