Mike Taylor's Web Log by Mike Taylor at

Over in web-bug #9726, there's an interesting issue reported against (which is already fixed because those peeps are classy):

Basically, they had an HTML <button> that when clicked would display:block a descendent <dialog> element that contained some hyperlinks to help you create a new project.

screenshot of button

The simplest test case:

  <a href="">do cool thing</a>

Problem is, clicking on an anchor with an href inside of a button does nothing in Firefox (and Opera Presto, which only 90s kids remember).

What the frig, web browsers.

But it turns out HTML is explicit on the subject, as it often is, stating that a button's content model must not have an interactive content descendant.

(and <a href> is totally, like, interactive content, itsho*)

Soooo, probably not a good idea to follow this pattern. And who knows what it means for accessibility.

The fix for glitch is simple: just make the <dialog> a sibling, and hide and show it the same way.

* in the spec's humble opinion

otsukare by Karl Dubost at

We often see code benchmarks. Some browser X HTML renderer is faster than browser Y renderer. Some JavaScript engine outperforms the competition by two folds.

While these benchmarks give a kind of instant gratification for the product, they always make me dubious coming from anyone. If the target is to outperform another browser, then I sense that nothing useful has really been accomplished. Even as a marketing technique, I don't think it's working.

When/if publishing a benchmark, focus on three things:

  • How this new code outperform the previous versions of the code? It's good to show that we care about our product and that we want to be faster where/when it matters.
  • How does this improve the user experience on some specific sites? Improving speed in controled environment like benchmarks is nice, but improving speed on real cases Web site is even better. Did it make the JavaScript-controled scrolling faster and smoother?
  • How did we get there? What are the steps which have been taken to improve the code performance? The coding tricks and techniques used to make it faster.

These will be benchmarks blog posts I like to read. So as a summary

Good benchmarks show 1. Outperform your own code 2. Real websites improvement demos 3. Give Technical explanations.


otsukare by Karl Dubost at

There's always a sequence of things I do before working on a new branch for development.

# Probably one of the most used command for me. (See below)
git status
# back to the master branch
git checkout master
# webcompat is my origin
git fetch webcompat
# updating to the latest version
git merge webcompat/master
# opening a new branch where 1677 is the issue number and 1 is the first attempt.
git checkout -b 1677/1

Most used git commands?

Let's see if my impression was correct.

grep -E '^git' ~/.bash_history | sort | uniq -c | sort -nr | head -n15
 563 git status
 383 git diff
 211 git checkout master
 131 git push origin master
 124 git branch -a
 117 git log
  61 git fetch webcompat
  51 git pull upstream master
  49 git merge webcompat/master
  45 git fetch upstream
  41 git log --oneline
  23 git fetch webcompat;git merge webcompat/master
  20 git pull
  20 git checkout master; git fetch upstream;git merge upstream/master
  19 git fetch upstream;git merge upstream/master

This previous one is too specific because it includes the full line. Let's constraint it to the git option. git status is still the winner.

→ awk '{print $1, $2}' ~/.bash_history | grep -E '^git' | sort | uniq -c | sort -nr | head -n15
 572 git status
 543 git commit
 509 git diff
 501 git checkout
 395 git push
 238 git branch
 193 git log
 186 git fetch
 136 git pull
 116 git add
  96 git merge
  82 git clone
  77 git rg
  37 git rebase
  31 git remote

If you are wondering what git rg is? It is coming from my ~/.gitconfig and is a courtesy of Anthony Ricaud.

        rg = "grep --heading --break -i"

Very useful grep baked into git.


otsukare by Karl Dubost at

We had a working business week for Mozilla All Hands. The big bi-annual meeting of the full company to work, discuss, cooperate and make wonderful things.

These are random notes not work related about thoughts accumulated during San Francisco week. What we notice in spaces and people are primary ourselves. It's often the start of a self-introspection more than anything else.

Meeting with my thoughts

  • crossing the border went smoothly. I was feeling good. No mobile device. Blank laptop.
  • Mission street areas from the bus. A bus of wealthy geeks watching the poor, the abandonned, the drifter from up there behind a window. It takes a blaze and spirit to start a revolution. The spirit is drowned inside the body.
  • This insecure feeling of the touristic areas when you never know if and when a driver will plow into the crowd or someone will draw a gun.
  • Chinatown is peaceful and calming environment for me. Something familiar, something I relate to.
  • The charm of the hills of San Francisco is a beautiful pain to my legs. The effort and the view are a gift.
  • Brands using pseudo-political messages to sell more stuff. Nauseous.
  • Exhausted.
  • Sleeping.
  • Plastic surgery is a thing.
  • Cable cars packed with tourists. Do locals still take the cable cars? Private buses to go to Silicon Valley. Dedicated transportation for tourists… What a broken world.
  • Noisy reception, rooms full of people too loud.
  • The emptiness of ads.
  • Long discussion with a friend walking across the San Francisco streets about everything, about nothing, about simple things. On the road, we share.
  • From coit tower, foggy dark Golden Gate vaporized in the horizon.
  • Sirens of fire trucks are frequent
  • A black old man clapped my hand when crossing and wished me a good day. I replied "you too". I don't know if he heard me.
  • I hear the cable cars tongtong tongtong from the hotel window.
  • Things we hear in SF "Oh crap, can someone stash my kinder eggs?"
  • Industrial buildings and hipster shops. The world of rich people is leveled.
  • Freezing wind.
  • Wonderful broth of a Pho Bo
  • A woman shouting "bitch" multiple times at the window of a Carl's restaurant.
  • The feeling of meeting too many people.
  • The feeling of meeting too few people.
  • A perfume shop clerk, old and elegant woman talked to me English, then Japanese, then French. Smile for the day.
  • Missing the cafe latte barista from Whistler All Hands.
  • USA and too big hotel rooms. Ridiculous use of space in a time where everything should be counted and saved.
  • Written culture of street signs.
  • Walking from the hotel to the bye bye event, a moment for long life discussions.
  • American college kids doing bbq. A certain image of USA.
  • Long streets without any shops.
  • overheard: "Let's start the day with a bloody mary" (at the airport at 8am)


Mike Taylor's Web Log by Mike Taylor at

7 years ago I tweeted my only good tweet:

please kill the text-shadow in ::selection. obsessive compulsive text highlighters like myself go blind

screenshot of text selection ugliness

(apologies for hideous screenshot, 2010 was a weird time for web design, I guess)

Some internet hipsters agreed, so they put a default text-shadow: none rule for ::selection in html5 boilerplate's main.css.

Anyways, we recently got a bug about nearly same exact issue: if you have a white background and set a white text-shadow on the copy (wat), things can get weird when someone makes a selection:

#wrapper {
  background-color: #fff;
.post-meta {
  text-shadow: 2px 0px 1px #fff;

So don't do that?

Anyways. The most important takeaway (for me) is that the devs over at don't follow me on twitter, which is super rude when you think about it.

otsukare by Karl Dubost at

webcompat life

  • Often tracking protection is confusing for people. I always wonder if it's because people are put in front of it in failure situation. Basically you discover something is not working because the site breaks, and you are later on told it is because of tracking protection. It's a negative feeling feature which doesn't show itself when everything is fine. I wonder if there would be a way to reverse that feeling. Something like, an individual site report on the blocking and a daily or weekly stats dashboard explaining what has been blocked. "Congratulations, Tracking Protection has blocked this week X of this, Y of that."
  • Webcompat Minutes published

webcompat issues dev

Interesting read


otsukare by Karl Dubost at

webcompat life

  • Jetlag and fatigue. Last week, a part of the Webcompat team had an intense work week in Berlin to discuss the precise parts of developing and the strategies around it.
  • it's my 3rd time in Berlin. À la Sei Shonagon, some pillow book notes:
    • Broken glasses in many streets.
    • People drink in the streets. Sometimes beer. Sometimes in the morning.
    • Organic shops or sections everywhere.
    • April is cold.
    • Graffiti and artsy life very active.
    • Mozilla office is in an area a bit dead.
    • The subway is based on a trust system. Free access to the platforms, punch your card to validate your ticket.
    • Children ride bikes as much as adults. Plenty of bike trailers too.
  • Developer tools and web compatibility

webcompat issues dev

Interesting read


otsukare by Karl Dubost at

webcompat life

  • Some issues takes a lot longer to analyze understand than what it seems at the start.

webcompat issues dev


When Can I Use updates by Alexis Deveria at

Two new developments to the Can I use site:

1. is now available over HTTPS! There's still a few kinks to work out before that becomes the new default but it's available today.

2. New Patreon account to enable an ad-free experience! When you support the site for as little as $1 USD/month and link your account, ads will no longer be loaded on the page. Once you're a patron just click the log in button at the bottom of the site to link your account. Your contributions are highly appreciated and help keep the site running!

otsukare by Karl Dubost at

webcompat life

  • Working on a replacement for our minutes script.
  • Booking flights to June meeting in San Francisco and thinking about my strategy with regards to data. Each time I book flights I can't help thinking about the absurdity of airlines and booking strategy.
  • My server for this site and a couple of others have changed place. For the last 15 years, my 1U Dell was hosted at W3C MIT. Thank you. I moved to Gandi in the meantime, but I'm exploring also something else.

webcompat issues dev


otsukare by Karl Dubost at

webcompat life

webcompat issues dev

To read


otsukare by Karl Dubost at

I have seen clever, thoughtful and hardworking people trying to be right about the CSS is not broken and CSS is broken. PopCorn. I will not attempt to be right on anything in this post. I'm just sharing a feeling.

Let me steal the image from this provocative tweet/thread. You can also read the thread in these tweets.


I guess looking at the image I understood how/why the discussions would never have any resolutions. Just let clarify a few things.

A Bit Of An Introduction

CSS means Cascading Style Sheets. Cascading Style Sheets (CSS) is a simple mechanism for adding style (e.g., fonts, colors, spacing) to Web documents.. Words have meanings. It is 20 years old spec wise. But the idea came from a proposal on www-talk on October 10, 1994. Fast forward, there is an ongoing effort to formalize CSS Object Model aka CSSOM defines APIs (including generic parsing and serialization rules) for Media Queries, Selectors, and of course CSS itself.

Let's look at the very recent CSS Grid, currently in Candidate Recommendation phase and starting to be well deployed in browsers. Look carefully at the prose. The word DOM is cited only twice in an example. CSS is a language for describing styling rules.

The Controversy

What people are argueing about and not discussing or dialoguing about is not about CSS, but how to apply the style rules to a document.

  • Some developers prefers to use style elements and files using the properties of the cascade and specificity (which are useful), aka CSS.
  • Some developers wants to apply the style on each individual node in the DOM using JavaScript to constraint (remove) the cascade and the specificity because they consider it annoying for their use case.

devtools screenshot

I do not have a clear cut opinion about it. I don't think CSS is broken. I think it is perfectly usable. But I also completely understand what the developers who wants to use JavaScript to set style on elements are doing. It makes me uncomfortable the same way that Flash (circa 2000s) or frame (circa 1995) was making me uncomfortable. It is something related with la rouille du Web (The Rusty Web). The perennity of what we create on the Web. I guess in this discussion there are sub-discussions about craft and its love, the Web perennity and the notion of Web industrialization.

There is one thing which rubs me in the wrong direction is when people talk about HTML and CSS with the "in JS" term associated. When we manipulate the DOM, create new nodes and associate style to it, we are not doing anymore HTML and CSS. We are basically modifying the DOM, which is a complete different layer. It's easy to see how the concerns are different. When we open a web site made with React for example, the HTML semantics is often gone. You could use only div and span and it would be exactly the same.

To better express my feeling, let's rephrase this:

You could use only div and span and it would be exactly the same.

It would become.

pronoun verb verb adverb noun conjunction noun conjunction pronoun verb verb adverb determiner noun.

then we would apply some JavaScript to convey meaning on it.


As I said I don't think I'm adding anything useful to the debates. I'm not a big fan of everything apps through JavaScript, maybe because I'm old or maybe because I value time.

I also would be curious for the advocates of applying styles to nodes in the DOM, if they made the experiment of generating (programmatically) a hierachical CSS from the DOM. Basically the salmon ladder in the river to go back to the source. I'm not talking about creating a snapshot with plenty of style attributes, but reverse engineering the cascade. At least just as an experiment to understand the two paths and what we could learn about it. It would minimize the CSS selectors, take advantage of the cascade, avoid as much as possible !important, etc.


otsukare by Karl Dubost at

Let's clear something out print in the code is bad. But sometimes it is useful when you need to quickly debug or understand what is happening. Just do not forget to remove them before committing.

On development, we use unittest and nose for testing the code. Running one set of tests is as easy as

nosetests tests/

and the result is:

Ran 3 tests in 0.175s


Though usually I prefer to run:

nosetests -v tests/

which reveals our inconsistency in naming. Probably my own mistake.

Check Cache-Control for issues. ... ok
Check ETAG for issues. ... ok
Checks if we receive a 304 Not Modified. ... ok

Ran 3 tests in 0.173s


But there is something which was bothering me for a long time. Let's say I put a print statement in the code anywhere, be in the test or in the application code. Even when tests are valid, I want to know the content of some variables. I want to make double sure I'm testing the right thing.

    def test_cache_control(self):
        '''Check Cache-Control for issues.'''
        rv ='/issues/100', environ_base=html_headers)
        print '\n\n{what}:\n{this}\n'.format(what="Headers", this=rv.headers)
        self.assertIn('cache-control', rv.headers)
        self.assertEqual(rv.cache_control.max_age, 0)

nose will swallow everything except when the test fails. I finally discover the right parameter (and it's probably obvious to others): --nocapture. This will make it possible to get the print messages.

nosetests -v --nocapture tests/
('secrets', '/Users/karl/code/')
Check Cache-Control for issues. ... 

Content-Type: text/html; charset=utf-8
Content-Length: 9981
Cache-Control: must-revalidate, private, max-age=0
ETag: "39a3c7d6fda546253a02927272a360db"
Date: Wed, 29 Mar 2017 07:49:19 GMT
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Content-Security-Policy-Report-Only: default-src 'none'; connect-src 'self'; font-src 'self'; img-src 'self' https://*; script-src 'self' 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; report-uri /csp-report

Check ETAG for issues. ... ok
Checks if we receive a 304 Not Modified. ... ok

Ran 3 tests in 0.190s


Hope it is useful for someone else. It was in the documentation but was not obvious to me when I read it a couple of times.

Don’t capture stdout (any stdout output will be printed immediately) [NOSE_NOCAPTURE]

And yes I'm removing this print right away before I forget.


otsukare by Karl Dubost at

I ran into this issue recently with httpie (The python code for doing http requests)

http --verbose GET

I was getting:

http: error: SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:590) while doing GET request to URL:

Huh? Then tried curl

curl -v

We get.

*   Trying
* Connected to ( port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
* Server certificate:
* Server certificate: DigiCert ECC Extended Validation Server CA
* Server certificate: DigiCert High Assurance EV Root CA
GET /home HTTP/1.1
User-Agent: curl/7.51.0
Accept: */*

< HTTP/1.1 200 OK
< Server: Cowboy
< Date: Sat, 25 Mar 2017 06:20:39 GMT
< X-Frame-Options: SAMEORIGIN
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< Content-Type: text/html; charset=utf-8
< Etag: W/"730ab400103d08252b84003a4e7862ff"
< Cache-Control: max-age=0, private, must-revalidate
< Set-Cookie: _marketing-tito_session=S3NERVovbjJmcEYvTGhkSktzVkQyZ3I0TXBOQ1lxTCs5LzhVMlhBN2ZKL0pTSjZCTi94VUo4b3N5RDNweGt2ZWNZTHc4MitNeGdtbjUvZXQ0RjVic1lCMlE3NVk2V21GNGFnYVpXZzVBMnM1bHg3bXpUOW1MZ1R5MlR5UnY3cVB3bzhzZER1eGRNTlNXTFlUVVMxWEhnPT0tLUZCNWQrcE9JcmU0OXJOeUY4YXJ0QXc9PQ%3D%3D--e96126ac335694d135c6a13b2effb22b486380b3; path=/; HttpOnly; Secure
< X-Request-Id: ce6a6522-1780-4b85-8ff5-4eeea24f8fa4
< X-Runtime: 0.007563
< Transfer-Encoding: chunked
< Via: 1.1 vegur
< Strict-Transport-Security: max-age=15768000
<!doctype html>
<html lang="en">

So I searched a bit. And I needed to upgrade a couple of things.

http uninstall httpie 

Then install the security update of requests. If you are wondering about --user, I do that all the time. It installs the 3rd party libraries in your own repo. It makes it safe when Apple upgrades python on your machine destroying all previous libraries installs.

pip install --user --upgrade requests[security]

This install a lot of stuff. Once done. You should get something like:

Successfully installed appdirs-1.4.3 asn1crypto-0.22.0 cffi-1.10.0 cryptography-1.8.1 idna-2.5 ipaddress-1.0.18 packaging-16.8 pyOpenSSL-16.2.0 pycparser-2.17 pyparsing-2.2.0 setuptools-34.3.2


pip install --user httpie

Which gives

Successfully installed httpie-0.9.9

Once done, you can check the state of things with

http --debug

This will spill out

HTTPie 0.9.9
Requests 2.13.0
Pygments 2.2.0
Python 2.7.10 (default, Jul 30 2016, 19:40:32) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
Darwin 16.4.0

<Environment {  … cut for Brevity… }>

And now retrying the request

http --traceback --print h GET

We get the right thing

HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Content-Type: text/html; charset=utf-8
Date: Sat, 25 Mar 2017 06:33:23 GMT
Etag: W/"ecdab4c883db75bc7e811a4360f62700"
Server: Cowboy
Set-Cookie: _marketing-tito_session=YVlLeFBWMXhwNml2cW54dC8xMk9DV1ZocWxQZ3BhVUlLUmlNK25SNHVyMHVsVnFGR1FYNGQ5SFRTZUNvMDRUU1VKbkR4Y2J3VStoZUJ0TWpteGIrcTMrYk9PQ21wTk1YRlU3cjVibC9NeEdXUUNlWFNoMHJjT3NWbnllUVMrVDMwZWJOZlZPWWQwSElUcG44WE5rWkhnPT0tLTZQNVZxVTYxYVhGUGNUV1htc1Jqb2c9PQ%3D%3D--d457a62be9a95ddf7ed17c19e2e006ed0a185be2; path=/; HttpOnly; Secure
Strict-Transport-Security: max-age=15768000
Transfer-Encoding: chunked
Via: 1.1 vegur
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: 7abb2983-4eee-46e0-8461-2d0b14f24056
X-Runtime: 0.008374
X-Xss-Protection: 1; mode=block


otsukare by Karl Dubost at

webcompat life

More people in the team, and we seem to have increased the number of meetings, maybe just a perception. But I liked the non verbal one that Sergiu did last week. Giving plenty of discussion points and the rest of us going to it for replying during the next couple of days.

webcompat issues dev

To read

Google says it can’t trust our self-hosted AMP pages enough to pre-render them. But they ask for a lot of trust from us. We’re supposed to trust Google to cache and host copies of our pages. We’re supposed to trust Google to provide some mechanism to users to get at the original canonical URL. I’d like to see trust work both ways.

I would add that the difference of power makes this trust unbalanced. And so when a power is asking for trust, we need very strong guarantee and counter-system once the trust has been breached.


otsukare by Karl Dubost at

webcompat life

I spent a big chunk of my time trying to figure out how to modify g in flask.

webcompat issues dev

  • Title choice for home page. Duckduckgo, google and Bing are giving very different results. In itself, this is interesting.
  • We have two sources of tests. Some in JavaScript that we call functional. And some in python which are unittests. It's sometimes a bit difficult to figure out where they should be. In this pull request, the contributor proposed to do it on the JavaScript side. But personally I have the feeling it should be on the python side. I'm not yet entirely convinced. My rationale is based on this is not involving user interaction at all, but this is generated by the application.
  • Needs to redefine a bit the SVG icons


otsukare by Karl Dubost at

webcompat life

webcompat issues dev

  • By introducing HTTP Caching to our HTML resources, I also introduced an issue. The bug report says that people can't login, logout. In fact they can. The issue is what the page looks like, it doesn't display that the user is logged-in. It's normal I initial put a max-age of one day in addition to the etag value. In browser speak, it means that if the browser has a cached copy it will not even try a conditional requests with If-None-Match. Because during the login process we are hitting the same resource. Users are receiving the previous cached copy and don't see that they have actually logged in. A force reload solves that. So instead of putting a max-age I can solve this with a no-cache. Unfortunately, browsers didn't respect the HTTP semantics of no-cache and decided to make it a no-store. Back to the departure case. must-revalidate, max-age=0 will solve it and force the conditional request.
  • Opened quick issue about our current twitter link based on the UX research currently done.
  • Discussions about issues with dependencies and how do we handle them?
  • Discussing about the Contact page friendliness
  • We currently have some outreachy participants. Time for review and help: review
  • Our issues title are… pretty poor for now.