Snippets

Build a Better Monster: Morality, Machine Learning, and Mass Surveillance

We built the commercial internet by mastering techniques of persuasion and surveillance that we’ve extended to billions of people, including essentially the entire population of the Western democracies. But admitting that this tool of social control might be conducive to authoritarianism is not something we’re ready to face. After all, we’re good people. We like freedom. How could we have built tools that subvert it?

[…]

The learning algorithms have no ethics or boundaries. There’s no slot in the algorithm that says “insert moral compass here”, or any way to tell them that certain inferences are forbidden because they would be wrong. In applying them to human beings, we leave ourselves open to unpleasant surprises.

The issue is not just intentional abuse (by trainers feeding skewed data into algorithms to affect the outcome), or unexamined bias that creeps in with in our training data, but the fundamental non-humanity of these algorithms.

[…]

So what happens when these tools for maximizing clicks and engagement creep into the political sphere?

This is a delicate question! If you concede that they work just as well for politics as for commerce, you’re inviting government oversight. If you claim they don’t work well at all, you’re telling advertisers they’re wasting their money.

Facebook and Google have tied themselves into pretzels over this. The idea that these mechanisms of persuasion could be politically useful, and especially that they might be more useful to one side than the other, violates cherished beliefs about the “apolitical” tech industry.

[…]

One problem is that any system trying to maximize engagement will try to push users towards the fringes. You can prove this to yourself by opening YouTube in an incognito browser (so that you start with a blank slate), and clicking recommended links on any video with political content. When I tried this experiment last night, within five clicks I went from a news item about demonstrators clashing in Berkeley to a conspiracy site claiming Trump was planning WWIII with North Korea, and another exposing FEMA’s plans for genocide.

This pull to the fringes doesn’t happen if you click on a cute animal story. In that case, you just get more cute animals (an experiment I also recommend trying). But the algorithms have learned that users interested in politics respond more if they’re provoked more, so they provoke. Nobody programmed the behavior into the algorithm; it made a correct observation about human nature and acted on it.

[…]

But even though we’re likely to fail, all we can do is try. Good intentions are not going to make these structural problems go away. Talking about them is not going to fix them.

We have to do something.

CSS deep-dive: matrix3d() for a frame-perfect custom scrollbar

I haven’t checked how accessible this is, and I’m torn on the concept of custom scrollbars, but this is interesting at the very least:

Custom scrollbars are extremely rare and that’s mostly due to the fact that scrollbars are one of the remaining bits on the web that are pretty much unstylable (I’m looking at you, date picker). You can use JavaScript to build your own, but that’s expensive, low fidelity and can feel laggy. In this article we will leverage some unconventional CSS matrices to build a custom scroller that doesn’t require any JavaScript while scrolling, just some setup code.

TL;DR:

You don’t care about the nitty gritty? You just want to look at the Nyan cat demo and get the library? You can find the demo’s code in our GitHub repo.

Building performant expand & collapse animations

Use scale transforms when animating clips. You can prevent the children from being stretched and skewed during the animation by counter-scaling them.

[…]

In this post we’re going to look over what’s involved if you want performant clip animations. If you want to see a demo, check out the Sample UI Elements GitHub repo.

Scrolling on the web: A primer

This is a fascinating and thorough dive into scrolling, and should be required reading for anyone writing JavaScript today:

Today, scrolling is still the most fundamental interaction on the web, and perhaps the most misunderstood. For instance, do you know the difference between the following scenarios?

  • User scrolls with two fingers on a touch pad
  • User scrolls with one finger on a touch screen
  • User scrolls with a mouse wheel on a physical mouse
  • User clicks the sidebar and drags it up and down
  • User presses up, down, PageUp, PageDown, or spacebar keys on a keyboard

If you ask the average web user (or even the average web developer!) they might tell you that these interactions are all equivalent. The truth is far more interesting.

Real-World Uses for MutationObserver

MutationObserver is a lesser known JavaScript feature which allows you to detect when elements in a web page are inserted, changed or removed. It is still relatively new, but it is supported by every modern browser.

The web is full of demos and tutorials of MutationObserver, but it’s pretty hard to find examples of it actually being used in practice. Even a search of Github is almost all libraries and test cases. We’ve had a couple occasions to use it at Eager however, which I now have the opportunity to share.

Client-side Image Optimization

Believe it or not, it’s actually possible to swap the src’s of img tags before the browser begins to load them. We can use that to optimize our images without changing the HTML source of our page. This code uses a FireSize service to handle the actual optimization.

We start by setting up a MutationObserver which will call our checkNode function with any new nodes which are added to the DOM:

Code language: JavaScript

var observer = new MutationObserver(function(mutations){
  for (var i=0; i < mutations.length; i++){
    for (var j=0; j < mutations[i].addedNodes.length; j++){
      checkNode(mutations[i].addedNodes[j]);
    }
  }
});
 
observer.observe(document.documentElement, {
  childList: true,
  subtree: true
});

If we run this code early in the head of the page, it will call our checkNode function with each DOM node as the browser parses the page’s HTML. This gives us the ability to check or mutate these nodes before they’ve ever been rendered.

We can define our checkNode function to decide if this is an image for us to optimize.

Code language: JavaScript

checkNode = function(addedNode) {
  if (addedNode.nodeType === 1 && addedNode.tagName === 'IMG'){
    addedNode.src = optimizeSrc(addedNode.src)
  }
}

Finally, we can define optimizeSrc to switch out our image’s src for an optimized one:

Code language: JavaScript

optimizeSrc = function(src) {
  return "//firesize.com/" + src;
}

For a complete implementation, take a look at our FireSize app source code.

Initializing When An Element Becomes Available on the Page

It’s a common pattern to wait for jQuery.ready or DOMContentLoaded to initialize code which depends on elements on the page. Those events don’t fire until the entire DOM has loaded however, meaning the page will start to be rendered before you have a chance to change or add to its content.

Our pattern from the image optimization solution also works for detecting when any element becomes available, allowing you to initialize code which depends on that element at the exact first moment it’s possible. We can redefine checkNode to instead check if our element matches an arbitrary selector:

Code language: JavaScript

checkNode = function(addedNode) {
  if (addedNode.nodeType === 1){
    if (addedNode.matches('.should-underline')){
      SmartUnderline.init(addedNode);
    }
  }
}

CSS Containment

When making a web app, or even a complex site, a key performance challenge is limiting the effects of styles, layout and paint. Oftentimes the entirety of the DOM is considered “in scope” for computation work, which can mean that attempting a self-contained “view” in a web app can prove tricky: changes in one part of the DOM can affect other parts, and there’s no way to tell the browser what should be in or out of scope.

[…]

The good news is that modern browsers are getting really smart about limiting the scope of styles, layout, and paint work automatically, meaning that things are getting faster without you having to do anything.

But the even better news is that there’s a new CSS property that hands scope controls over to developers: Containment.

The contain property

CSS Containment is a new property, with the keyword contain, which supports four values:

  • layout
  • paint
  • size
  • style

Each of these values allows you to limit how much rendering work the browser needs to do.

Note that this is currently only supported in Blink browsers. Firefox has a partial implementation behind a flag, and Edge is under consideration.

Information Literacy Is a Design Problem

Every decision we make influences how information is presented in the world. Every presentation adds to the pattern. No matter how innocuous our organization, how lowly our title, how small our user base—every single one of us contributes, a little bit, to the way information is perceived.

Are we changing it for the better?

While it’s always been crucial to act ethically in the building of the web, our cultural climate now requires dedicated, individual conscientiousness. It’s not enough to think ourselves neutral, to dismiss our work as meaningless or apolitical. Everything is political. Every action, and every inaction, has an impact.