Christian Heilmann

Author Archive

Unleashing the web multiverse at web unleashed

Sunday, September 15th, 2019

Final presentation by Jason Pamental

I’m in the lounge at YYZ waiting for my flight back to London after attending Web Unleashed in Toronto for the second time. Sadly enough I couldn’t be there for the whole event, but arrived late in the evening of the first day. I’m saying sadly, because I had an excellent time and I am impressed with the line-up the people at FITC managed to bring together for this event.

Those attending the event were treated to talks and workshops by amazing people I’ve met before and keep loving to see:

Wes Bos, Simona Cotin, Chris Coyier, Frédéric Harper, Henri Helvetica, Stefan Judis, Ankita Kulkarni, Jason Lengstorf, Jen Looper, Mina Markham, Jason Pamental, Kyle Simpson, Catt Small, Martin Splitt, Carl Sziebert and Shirley Wu.

And a few new ones I was impressed with:

Andréa Crofts, Kevin Daly, Zoe Daniels, Piyali Dey, Helen Kontozopoulos, Joyce Lin, Anne Thomas.

In general, there is a lot to look forward to when the video recordings will be released and if not, you should try to get a ticket next time.

I loved the seamless organisation, the way you got treated as a presenter and the general professionalism of the event. The catering was incredible, the stage tech worked (except for a mix-up at Wes Bos’ talk which he handled like the champ he is) and it is so useful to be in the same hotel as the event. Both the Powerpoint Karaoke night and the MediaTemple afterparty were in walking distance and entertaining without being overwhelming.

My contribution to the conference was one of the opening talks on the second day. The slides are available on notist, and I will write up a detailed post on the message and the ideas of it when I am done posting this.

View Into the Web Multiverse on Notist.

I love that as the last talk of the day, the MC Jason Pamental delivered an presentation of his overall impression of each of the talks and reminding the audience of what to take home from them. Far too many conferences just peter out on the second day without much fanfare, which always makes me feel a bit disappointed. Well done.

All in all, Web Unleashed is well worth the trip and the money, and I love how pragmatic and at the same time impactful it is.

(Btw, the way to get a good list of the speakers was easy doing this in Devtools):

let list = [];
document.querySelectorAll('.speaker-name').forEach(
  el => { list.push((el.innerHTML.trim()))}
);
console.log(list.join(', '));

Some impressions:

Jason Lengstorf and Chris Coyier
Jason Lengstorf and Chris Coyier in the speaker room

Wes Bos presenting like a champ
Wes Bos presenting

Fruit Salad with FITC logo
Blackberry’s involvement

Thank you to all involved, I had a lot of excellent conversations and a wonderful time. I shall be back.

Avocode interviewed me about my career and what comes next

Friday, August 30th, 2019

The nice folks at Avocode have a series of blog posts where they interview important people of the web and ask them about their history and career. Probably by accident, I ended on their invite list and they just published a long blog post of me explaining some things.

Chris Heilmann article

The questions we answered were in detail:

  • Hi Chris. Thanks for taking the time. Let’s start with who you are and what you do?
  • You’re the legend of the IT industry, and I’m thrilled to hear your journey towards development. When was the moment you knew you wanted to become a developer?
  • You’ve been using JavaScript since it came out, how would you compare the first version with what we use these days?
  • You worked as a Principal Developer Evangelist at Mozilla. What is your favorite project that you launched while being there?
  • Since 2015, you joined Microsoft. How did you end up here?
  • When you joined Microsoft, you came to refresh their “browser activities” and form a team that was responsible for them. Tell us about the obstacles you faced during the process.
  • How would you describe the journey of Internet Explorer and the last years of its life before being deprecated?
  • It’s been 4 years since the initial release of Microsoft Edge. What do you think about its journey?
  • Microsoft is on the rise of contributing to open-source projects. The acquisition of GitHub is another hint that Microsoft takes open-source seriously. What do you think about large corporations contributing to open-source?
  • Speaking of GitHub, besides the Visual Studio IDE, Microsoft now “owns” Visual Studio Code and Atom editors. They even share a framework that powers them — Electron. Are you using any of these?
  • We mentioned Electron, another GitHub project popular in the web-dev community. Many people from Microsoft help out with Electron. What do you think about web technologies landing in the “desktop world” thanks to Electron? Slack, VS Code, Spotify, Avocode depend on them. This, in turn, makes our computers run slower. Do you have any prediction where this trend will lead us?
  • There are several Machine Learning projects, and research groups that focus on automatic code generation, locating and fixing bugs automatically, etc. Do you see this becoming the next big thing anytime soon?
  • Do you have any tips on coming up with dev team code standards and maintaining them at all times? How can product managers educate their team in this matter?
  • What’s an interesting or fun fact about yourself we wouldn’t find on your social media?
  • What do you like to do when you’re not working?
  • Where is the best place for people to connect with you online?

“Tweet this page” bookmarklet

Friday, August 23rd, 2019

Update: Moved the code to GitHub, make sure to drag it from there to your toolbars
Update: Fixed now for Chrome – there were some issues with whitespace :(

I like tweeting about pages I read in the following format:

"Headline"
https://example.com

Most “share this” buttons add a lot of cruft and if there is none, it is annoying having to copy the text first and then the URL into Twitter.

With this bookmarklet, you can highlight some text, click the bookmarklet and get a tweet window in a new tab. This is the source in a more readable manner – this will not work as a bookmarklet, see the link below instead!

(function(){
    n=getSelection().anchorNode;
    if(!n) {
        t = document.title;
    } else {
        t = n.nodeType === 3 ? n.data : n.innerText;
    }
    t = 'β€œ' + t.trim() + '”\n\n';
    window.open(
        `https://twitter.com/intent/tweet?text=
        ${encodeURIComponent(t)}
        ${document.location.href}`
    )
})();

Explanation:

  • We wrap the whole thing in an IIFE to avoid the browser redirecting to “javascript://”
  • We get the anchorNode of the current Selection object
  • If there is no highlighted text, we grab the document title
  • We check the type. If it’s a text node, we read the data, if it is HTML, we get the innerText
  • We remove any whitespace, add the quotes and some line breaks
  • We open a window (which these days results in a new tab) and call the Twitter intend with the text followed by two line breaks and the URL of the document.

That’s it. Drag the bookmarklet to the toolbar from the GitHub Demo page or check the code.

Voilà, happy tweeting.

Quick tip: using scrollIntoView() to show added elements to a container with overflow

Friday, August 9th, 2019

Often we want to have an interface where we have a container with overflow: scroll with a header and a footer.
One problem with that is that when we add new elements to the container, they do get added to the end of it but the element won’t show up before the user scrolls down.

In the past we hacked around this issue by comparing scrollHeight and clientHeight and setting the scrollTop property of the element. This is error prone and seems overly complicated.

Enter scrollIntoView. Using this API ensuring that a new element shows up to the user is as simple as calling it on the element itself.

Say we have the following list of characters and a button to add more of them.

HTML:

<div class="scrollbody">
    <ul>
        <li>Billy Butcher</li>
        <li>Hughie Campbell</li>
        <li>Mother's Milk</li>
        <li>The Frenchman</li>
  </ul>
</div> 
<button>Add new character</button>

In the CSS, we limit the body to scroll and set it to overflow.

.scrollbody {
  height: 6em;
  overflow: scroll;
}

With a bit of JavaScript, we can now add new characters every time we click the button:

let characters = ['The Female (of the Species)',
'Lieutenant Colonel Greg D. Mallory','The Legend','The Homelander',
'Black Noir','Queen Maeve','A-Train','The Deep','Jack from Jupiter',
'The Lamplighter','Starlight','Mister Marathon','Big Game',
'DogKnott','PopClaw','Blarney Cock','Whack Job',
'Gunpowder','Shout Out'];
 
let count = 0;
document.querySelector('button').addEventListener('click', (ev) => {
    if (count < characters.length) {
    let item = document.createElement('li');
    item.innerText = characters[count];
    document.querySelector('ul').appendChild(item);
    count = count + 1;
  }
  ev.preventDefault;
});

Now, if you try this out, you see that the new characters are in fact added, but not visible until you scroll down to them.

elements not showing until the user scrolls

That’s bad. To remedy this, you all you need to to is to add the scrollIntoView call after adding the new list item:

/* list of characters */
let count = 0;
document.querySelector('button').addEventListener('click', (ev) => {
    if (count < characters.length) {
    let item = document.createElement('li');
    item.innerText = characters[count];
    document.querySelector('ul').appendChild(item);
 
    item.scrollIntoView();
 
    count = count + 1;
  }
  ev.preventDefault;
});

scrollintoview showing the new elements

As an extra bonus, you can define the behaviour of the scroll to be smooth, which scrolls it in slowly and not as jarringly:

/* list of characters */
let count = 0;
document.querySelector('button').addEventListener('click', (ev) => {
    if (count < characters.length) {
    let item = document.createElement('li');
    item.innerText = characters[count];
    document.querySelector('ul').appendChild(item);
 
    item.scrollIntoView({behavior: 'smooth'});
 
    count = count + 1;
  }
  ev.preventDefault;
});

scrollintoview showing the new elements smoothly

Another reminder to keep looking into what’s in the standard these days rather than finding an old solution on StackOverFlow and keep too complex and not browser-optimised code alive.

Using CSS Custom attributes generated by JavaScript as a handover mechanism

Monday, July 29th, 2019

Update: there was a simplification about Custom Attributes being not supporting concatenation, thanks to Sime Vidas, Brian Kardell and Greg Whitworth to set this straight.

Over the last few iterations of CSS the boundaries between CSS and JavaScript started to blur. CSS was a static language, meant to define colours, look and feel, but not interactivity. You could use percentages in dimensions as sort of interactivity to the enviroment, but reacting to things changing was the job of JavaScript.

In the days of old HTML was there to give structure, CSS look and feel and JavaScript interactivity. Or, as I put it in my book in 2006, if your website were a movie HTML would be the script, CSS the cinematography and direction and JavaScript the special effects.

Nowadays, CSS is much more powerful. We have animations, transitions, calc() and much more flexible values like em, rem, vw, vh and more. We also have interactivity with pseudo selectors like hover, focus and states of interactive elements like buttons. We can even hack with checkboxes to write full games in pure CSS.

This is great! CSS aficionados are much more likely to have the patience and knowledge to make an animation or interaction look and behave exactly right. And CSS engines are responsible to perform well and not clobber the interactivity or battery life of the end user device. Browser makers can concentrate on optimising the engine rather than competing with the developer on who has the job to keep things smooth.

However, there are still boundaries and use cases where CSS is not enough, and you need JavaScript. Often these are about reading the current state of something happening to the browser window or an interaction not considered in the CSS spec.

Switching fully to JavaScript in that case feels like a knee-jerk reaction and it makes more sense to me to find a way for JavaScript and CSS to interact. JavaScript to read the value and to make it available to CSS in some way.

In the past, the only way to do that was to store classes on parent elements or remove classes when certain conditions were met. But with Custom Properties (“CSS variables”), it has become much easier to interact between JavaScript and CSS.

Custom properties allow you to set “variables” in CSS and use them later. For example:

::root {
  --company-blue: #369;
} 
 
h1 {
  color: var(--company-blue);
}

Custom properties are somehow limited and are not strings like they are in CSS preprocessors, so you can’t readily concatenate them Custom properties work differently to CSS variables in preprocessors. You can concatenate them, but there are limitations.

Thanks to Šime Vidas who showed a working demo on Twitter and to Brian Kardell pointing to the discussion on the CSS standards group .

As my colleague Greg Whitworth explains:

This is not actually true regarding custom props. The issue I think you’re primarily referring to are potential limitations in CSS in general, although I noticed that Sime already showed you that concatenation can be done but probably not in all scenarios where the only desire is to join actual strings (eg: “bar” calc(5 + 8) will get converted to \”foo\” calc(58) since it isn’t a valid calc and thus those are converted to a string as well but with escaped quotes. Everything within the variable is tokenized, so it can be a string or not depending on what the value is determined by the tokenizer. If it isn’t an invalid ident but isn’t one that can be matched, then it is converted to a string for use within CSS. Anything passed to JS is converted to a string. You can see this in this JSBin

The simplest way to alter CSS custom properties is to use calc() to multiply them with a value:

::root {
  --startwidth: 200;
} 
 
h1 {
  width: (var(--startwidth) * 1px);
}
h2 {
  width: (var(--startwidth) * 0.5px);
}

Now, as you can also define custom properties in JavaScript and add them to the styles collection of any element, this is a great way to only use JavaScript to read a value and leave the rest to CSS.

For example, if you wanted to know how far the document has scrolled, you can read this in JavaScript with an event handler and modify a CSS custom attribute:

JavaScript:

window.addEventListener('scroll', (e) => {
  document.body.style.setProperty('--scrolly', window.scrollY);
});

CSS:

h1 {
  position: fixed;
  width: calc(var(--scrolly)*1px);  
  background: #339;
}

You can try this out in this JSBin

By no means, this is a sensible demo, but I really like the fact that you can use JavaScript to reach where CSS can not, and still allow CSS to be the main driver and definition of interactivity.