emGee Software Solutions Custom Database Applications

Share this

Web Technologies

Higher Order Functions

Echo JS - Sat, 08/11/2018 - 15:14
Categories: Web Technologies

The Cost of JavaScript in 2018

CSS-Tricks - Fri, 08/10/2018 - 08:40

Even though we mentioned it earlier, I thought this outstanding post by Addy Osmani all about the performance concerns of JavaScript was still worth digging into a little more.

In that post, Addy touches on all aspects of perf work and how we can fix some of the most egregious issues, from setting up a budget to “Time-to-Interactive” measurements and auditing your JavaScript bundles.

Embrace performance budgets and learn to live within them. For mobile, aim for a JS budget of < 170KB minified/compressed. Uncompressed this is still ~0.7MB of code. Budgets are critical to success, however, they can’t magically fix perf in isolation. Team culture, structure and enforcement matter. Building without a budget invites performance regressions and failure.

Super specific and super practical!

Surprisingly, Addy mentions that “the median webpage today currently ships about 350KB of minified and compressed JavaScript,” which seems like an awful lot lower than I’d expected, if I'm being honest. The stat that scares me most is that the median webpage takes around fifteen whole seconds until it’s interactive. And pulling all that JS into a Web Worker or caching with Service Workers won't even make up that time to interaction. Yikes.

Another key point: not all bytes are equal. For example, 200KB of JavaScript is not equal to a 200KB JPG image file:

A JPEG image needs to be decoded, rasterized, and painted on the screen. A JavaScript bundle needs to be downloaded and then parsed, compiled, executed —and there are a number of other steps that an engine needs to complete. Just be aware that these costs are not quite equivalent.

Direct Link to ArticlePermalink

The post The Cost of JavaScript in 2018 appeared first on CSS-Tricks.

Categories: Web Technologies

Switch font color for different backgrounds with CSS

CSS-Tricks - Fri, 08/10/2018 - 06:58

Ever get one of those, "I can do that with CSS!" moments while watching someone flex their JavaScript muscles? That’s exactly the feeling I got while watching Dag-Inge Aas & Ida Aalen talk at CSSconf EU 2018.

They are based in Norway, where WCAG accessibility is not a just good practice, but actually required by law (go, Norway!). As they were developing a feature that allows user-selectable color theming for their main product, they faced a challenge: automatically adjusting the font color based on the selected background color of the container. If the background is dark, then it would be ideal to have a white text to keep it WCAG contrast compliant. But what happens if a light background color is selected instead? The text is both illegible and fails accessibility.

They used an elegant approach and solved the issue using the "color" npm package, adding conditional borders and automatic secondary color generation while they were at it.

But that’s a JavaScript solution. Here’s my pure CSS alternative.

The challenge

Here is the criteria I set out to accomplish:

  • Change the font color to either black or white depending on the background color
  • Apply the same sort of logic to borders, using a darker variation of the base color of the background to improve button visibility, only if background is really light
  • Automatically generate a secondary, 60º hue-rotated color
Working with HSL colors and CSS variables

The easiest approach I could think for this implies running HSL colors. Setting the background declarations as HSL where each parameter is a CSS custom property allows for a really simple way to determine lightness and use it as a base for our conditional statements.

:root { --hue: 220; --sat: 100; --light: 81; } .btn { background: hsl(var(--hue), calc(var(--sat) * 1%), calc(var(--light) * 1%)); }

This should allow us to swap the background to any color we’d like at runtime by changing the variables and running an if/else statement to change the foreground color.

Except... we don’t have if/else statements on CSS… or do we?

Introducing CSS conditional statements

Since the introduction of CSS variables, we also got conditional statements to go with them. Or sort of.

This trick is based on the fact that some CSS parameters get capped to a min and max value. For instance, think opacity. The valid range is 0 to 1, so we normally keep it there. But we can also declare an opacity of 2, 3, or 1000, and it will be capped to 1 and interpreted as such. In a similar fashion, we can even declare a negative opacity value, and get it capped to 0.

.something { opacity: -2; /* resolves to 0, transparent */ opacity: -1; /* resolves to 0, transparent */ opacity: 2; /*resolves to 1, fully opaque */ opacity: 100; /* resolves to 1, fully opaque */ } Applying the trick to our font color declaration

The lightness parameter of an HSL color declaration behaves in a similar way, capping any negative value to 0 (which results in black, whatever the hue and saturation happens to be) and anything above 100% is capped to 100% (which is always white).

So, we can declare the color as HSL, subtract the desired threshold from the lightness parameter, then multiply by 100% to force it to overshoot one of the limits (either sub-zero or higher than 100%). Since we need negative results to resolve in white and positive results to resolve in black, we also have to invert it multiplying the result by -1.

:root { --light: 80; /* the threshold at which colors are considered "light." Range: integers from 0 to 100, recommended 50 - 70 */ --threshold: 60; } .btn { /* Any lightness value below the threshold will result in white, any above will result in black */ --switch: calc((var(--light) - var(--threshold)) * -100%); color: hsl(0, 0%, var(--switch)); }

Let’s review that bit of code: starting from a lightness of 80 and considering a 60 threshold, the subtraction results in 20, which multiplied by -100%, results in -2000% capped to 0%. Our background is lighter than the threshold, so we consider it light and apply black text.

If we had set the --light variable as 20, the subtraction would have resulted in -40, which multiplied by -100% would turn 4000%, capped to 100%. Our light variable is lower than the threshold, therefore we consider it a "dark" background and apply white text to keep a high contrast.

Generating a conditional border

When the background of an element becomes too light, it can get easily lost against a white background. We might have a button and not even notice it. To provide a better UI on really light colors, we can set a border based on the very same background color, only darker.

A light background with a dark border based on that background color.

To achieve that, we can use the same technique, but apply it to the alpha channel of a HSLA declaration. That way, we can adjust the color as needed, then have either fully transparent or fully opaque.

:root { /* (...) */ --light: 85; --border-threshold: 80; } .btn { /* sets the border-color as a 30% darker shade of the same color*/ --border-light: calc(var(--light) * 0.7%); --border-alpha: calc((var(--light) - var(--border-threshold)) * 10); border: .1em solid hsla(var(--hue), calc(var(--sat) * 1%), var(--border-light), var(--border-alpha)); }

Assuming a hue of 0 and saturation at 100%, the above code will provide a fully opaque, pure red border at 70% the original lightness if the background lightness is higher than 80, or a fully transparent border (and therefore, no border at all) if it’s darker.

Setting the secondary, 60º hue-rotated color

Probably the simplest of the challenges. There are two possible approaches for it:

  1. filter: hue-rotate(60): This is the first that comes to mind, but it’s not the best solution, as it would affect the color of the child elements. If necessary, it can be reversed with an opposite rotation.
  2. HSL hue + 60: The other option is getting our hue variable and adding 60 to it. Since the hue parameter doesn’t have that capping behavior at 360 but instead wraps around (as any CSS <angle> type does), it should work without any issues. Think 400deg=40deg, 480deg=120deg, etc.

Considering this, we can add a modifier class for our secondary-colored elements that adds 60 to the hue value. Since self-modifying variables are not available in CSS (i.e. there’s no such thing as --hue: calc(var(--hue) + 60) ), we can add a new auxiliary variable for our hue manipulation to our base style and use it in the background and border declaration.

.btn { /* (...) */ --h: var(--hue); background: hsl(var(--h), calc(var(--sat) * 1%), calc(var(--light) * 1%)); border:.1em solid hsla(var(--h), calc(var(--sat) * 1%), var(--border-light), var(--border-alpha)); }

Then re-declare its value in our modifier:

.btn--secondary { --h: calc(var(--hue) + 60); }

Best thing about this approach is that it’ll automatically adapt all our calculations to the new hue and apply them to the properties, because of CSS custom properties scoping.

And there we are. Putting it all together, here’s my pure CSS solution to all three challenges. This should work like a charm and save us from including an external JavaScript library.

See the Pen CSS Automatic switch font color depending on element background.... FAIL by Facundo Corradini (@facundocorradini) on CodePen.

Except it doesn’t. Some hues get really problematic (particularly yellows and cyans), as they are displayed way brighter than others (e.g. reds and blues) despite having the same lightness value. In consequence, some colors are treated as dark and given white text despite being extremely bright.

What in the name of CSS is going on?

Introducing perceived lightness

I’m sure many of you might have noticed it way ahead, but for the rest of us, turns out the lightness we perceive is not the same as the HSL lightness. Luckily, we have some methods to weigh in the hue lightness and adapt our code so it responds to hue as well.

To do that, we need to take into consideration the perceived lightness of the three primary colors by giving each a coefficient corresponding to how light or dark the human eye perceives it. This is normally referred to as luma.

There are several methods to achieve this. Some are better than others in specific cases, but not one is 100% perfect. So, I selected the two most popular, which are good enough:

  • sRGB Luma (ITU Rec. 709): L = (red * 0.2126 + green * 0.7152 + blue * 0.0722) / 255
  • W3C method (working draft): L = (red * 0.299 + green * 0.587 + blue * 0.114) / 255
Implementing luma-corrected calculations

The first obvious implication from going with a luma-corrected approach is that we cannot use HSL, since CSS doesn’t have native methods to access the RGB values of an HSL declaration.

So, we need to switch to an RBG declaration for the backgrounds, calculate the luma from whatever method we choose, and use it on our foreground color declaration, which can (and will) still be HSL.

:root { /* theme color variables to use in RGB declarations */ --red: 200; --green: 60; --blue: 255; /* the threshold at which colors are considered "light". Range: decimals from 0 to 1, recommended 0.5 - 0.6 */ --threshold: 0.5; /* the threshold at which a darker border will be applied. Range: decimals from 0 to 1, recommended 0.8+ */ --border-threshold: 0.8; } .btn { /* sets the background for the base class */ background: rgb(var(--red), var(--green), var(--blue)); /* calculates perceived lightness using the sRGB Luma method Luma = (red * 0.2126 + green * 0.7152 + blue * 0.0722) / 255 */ --r: calc(var(--red) * 0.2126); --g: calc(var(--green) * 0.7152); --b: calc(var(--blue) * 0.0722); --sum: calc(var(--r) + var(--g) + var(--b)); --perceived-lightness: calc(var(--sum) / 255); /* shows either white or black color depending on perceived darkness */ color: hsl(0, 0%, calc((var(--perceived-lightness) - var(--threshold)) * -10000000%)); }

For the conditional borders, we need to turn the declaration into a RGBA, and once again, use the alpha channel to make it either fully transparent or fully opaque. Pretty much the same thing as before, only running RGBA instead of HSLA. The darker shade is obtained by subtracting 50 from each channel.

There's a really weird bug on WebKit on iOS that will show a black border instead of the appropriate color if using variables in the RGBA parameters of the shorthand border declaration. The solution is declaring the border in longhand.
Thanks Joel for pointing out the bug!

.btn { /* (...) */ /* applies a darker border if the lightness is higher than the border threshold */ --border-alpha: calc((var(--perceived-lightness) - var(--border-threshold)) * 100); border-width: .2em; border-style: solid; border-color: rgba(calc(var(--red) - 50), calc(var(--green) - 50), calc(var(--blue) - 50), var(--border-alpha)); }

Since we lost our initial HSL background declaration, our secondary theme color needs to be obtained via hue rotation:

.btn--secondary { filter: hue-rotate(60deg); }

This is not the best thing in the world. Besides applying the hue rotation to potential child elements as previously discussed, it means the switch to black/white and border visibility on the secondary element will depend on the main element’s hue and not on its own. But as far as I can see, the JavaScript implementation has the same issue, so I’ll call it close enough.

And there we have it, this time for good.

See the Pen CSS Automatic WCAG contrast font-color depending on element background by Facundo Corradini (@facundocorradini) on CodePen.

A pure CSS solution that achieves the same effect as the original JavaScript approach, but significantly cuts on the footprint.

Browser support

IE is excluded due to the use of CSS variables. Edge doesn’t have that capping behavior we used throughout. It sees the declaration, deems it nonsense, and discards it altogether as it would any broken/unknown rule. Every other major browser should work.

The post Switch font color for different backgrounds with CSS appeared first on CSS-Tricks.

Categories: Web Technologies

React Native JavaScript framework stumbles

InfoWorld JavaScript - Thu, 08/09/2018 - 12:15

Once hailed as a breakthrough in mobile development, Facebook’s React Native framework is stumbling, with users reassessing their commitment to the technology and Facebook looking to overhaul it.

React Native has been used at companies like Uber to Tesla, Instagram, and Facebook itself. Late in 2015, analyst firm IDC saw React Native as offering a new paradigm for hybrid development, freeing developers from the Webview component and delivering native performance. React Native opened the native device platform to web developers, said IDC. But IDC did add the caveat that the technology was still immature at the time.

To read this article in full, please click here

Categories: Web Technologies

Five interesting ways to use Sanity.io for image art direction

CSS-Tricks - Thu, 08/09/2018 - 06:57

When we saw Chris put up a list of cloud-hosted data-stores, we couldn't resist letting him know that we also had one of those, only ours is a fully featured CMS that come with a rich query language and an open source, real time, collaborative authoring tool that you can tailor to your specific needs using React. It's called Sanity.io.

“Add us to your list!” we asked Chris. “No, your stuff is interesting, can’t you write about you,” he replied. “Maybe something that would be useful for people working with images.” Challenge accepted!

Systems like Sanity wants to free your content from the specific page it happens to be sitting on, so that you can flow it through APIs. That way you can reuse your painstakingly crafted content anywhere you need it.

So, what does this mean for images?

Images are the odd ones out. We can capture documentation articles, pricing plans or project portfolios as potentially complex, but ultimately graspable data-structures that machines can query and process in many useful ways. But images? They're really just bags of pixels sitting at the end of a CDN, aren't they?

We came up with some ideas anyway because everyone needs images and images should be just as willing to travel to new and exciting places and services as the rest of your structured stuff.

So, here we are with a medium-sized bag of image tricks you can pull off with Sanity.

1. Grab the palette from image metadata

Ever tried to overlay text over a random image submitted by a user? How did that work out? We've usually ended submitting our images to filters till they're predictable and skulked home with a moody expression.

We thought it would be nice to ship an image palette with your pictures so you can select between dark and light typography as well as pair visual elements with image color. This makes legibility so much better and prevents clashes between the colors of images and text.

See the Pen Access image colors as metadata in Sanity by Knut Melvær (@kmelve) on CodePen.

2. Get low-quality image placeholders

However fast and nearby your CDN is, it still takes time to transmit large image files. So, we included a Low-Quality Image Placeholder (LQIP) with your image metadata. It's a base64 encoded string of your photo at 20px width. Getting LQIP in the first request lets you bake a proxy image right into the HTML.

<figure style={{ backgroundImage: `url(${mainImage.metadata.lqip})`, paddingTop: `calc(100% / ${mainImage.metadata.dimensions.aspectRatio})` }} > <img src={`${mainImage.url}`} /> </figure>

A challenge with image placeholders is being able to predict the dimensions of the image in a fluid layout. In this example, we used the aspect ratio that also comes in the metadata object to calculate the padding-top trick. That means that you don't have to calculate the aspect ratio yourself, and e.g. output it as a custom property combined with CSS variables.

See the Pen Get Low Quality Image Placeholders out of the box by Knut Melvær (@kmelve) on CodePen.

3. Use on-demand image transforms

You should be able to store archival originals and get the image in whatever resolution and format you need. Go ahead, upload your 268 megapixel TIFF, and ask for a 128x128 cropped JPEG with a 50% blur.

The transforms are generated from URL-parameters and generated on the first request. We cache the result locally and on a CDN so many requests for the same result image will be super snappy.

Take this image of the Carina Nebula. We uploaded a 29.566 x 12.960 version of it. Let’s say we wanted a PNG version with a 500px width. Attach ?w=500&fm=png to the image URL, and there it is:

Source File

Not only is it hard to hear screaming in space, it's also hard to judge directions. But let’s say you need to rotate the image. Well, you can append &or=90 and it's tilted 90 degrees (and scale it down to 128px):

Source File

Not to ruffle any feathers at NASA, but if you want to simulate spherical aberration on your new 1.5bn USD telescope, you can do that by adding ?blur=30 to the image-url!

Source File

The image pipeline is good for your SVGs as well. Say you need to offer a JPG Open Graph (og:image) to Facebook or you have an urgent need to add this SVG of a forklift as a Slack emoji:

Source File

Get the 128x128 PNG version you need, by appending the URL parameters w=128&h=128&fm=png just like this.

You also have control of background color, with bg=<hexcolor> Let's say we, for some reason, wanted this forklift on a lovely purple background.

And, finally, if you want to link to this image and trigger a download for the user, you can append dl=<suggested file-name> to make it happen.

Download the Image

It's not always as fun as this to mess around with URL parameters, so we made a JavaScript library that makes it a bit easier. Install it with npm install --save @sanity/image-url and learn how to use it (we use it in the demos throughout this post).

4. Crop and scale to fit around a focus point

Those pesky images with their fixed aspect ratios. In addition to not knowing the pixel density of the output device, you often don't even know what crop would be best suited for the layout. Even on a single website, you'll often use the same image in different layouts, and often need to serve them up to third parties, like Facebook, that expects specific aspect ratios.

Custom crop and hotspot in Sanity Studio

To ease the pain of dealing with this, we've let content editors set hotspots and crops for images. We have also made a JavaScript package that does all the hard work of making the correct image transform URLs for you. Simply pass an image asset and the size you want and we'll figure out the crop and scale.

See the Pen Custom crop and hotspots by Knut Melvær (@kmelve) on CodePen.

5. Make a real-time photomap

If this isn't turning it up to 11, it's at least a good 10.5.

We can extract EXIF and geo-location data from an image. EXIF-data contains information about the camera state when the photo was taken (e.g. exposure, aperture, lens, if the flash went off etc). Due to privacy concerns (we take GDPR-compliance super seriously) we have turned the feature off by default, but if you set [options: { metadata: ['exif', 'location' ] } in your schema options, they will be included.

We have made a tiny demo that lets you upload an image and, if it has location data (e.g. typically those you take with your phone), it will automatically pop up in the map — because the API is real-time with listeners!

See the Pen Shared Realtime Photo Map by Knut Melvær (@kmelve) on CodePen.

If you want to test out Sanity and these features yourself, you can get started with writing npm i -g @sanity/cli && sanity init. Even though the CLI guides you through the installation process, it's worth checking out the documentation (if not for the illustrations alone) and there are always people that want to help out with the nitty gritty in our Slack group.

The post Five interesting ways to use Sanity.io for image art direction appeared first on CSS-Tricks.

Categories: Web Technologies

New on Wufoo: Form Manager Beta, File Manager Beta, Entry Manager Beta

CSS-Tricks - Thu, 08/09/2018 - 06:54

Wufoo really is firing on all cylinders lately! As you may know, I've been using Wufoo here on this site, and pretty much every other site I've ever made, to power the web forms for over a decade. That's a dang long time, which more than proves to me Wufoo is a form solution to trust. But also a product that improves!

There is a new Form Manager, Entry Manager, and File Manager.

Enable the beta stuff through the Account menu:

The new Form Manager has a modern and clean look. You can tell this has been a massive cleanup and give them better place to iterate from:

The Entry Manager is the biggest upgrade so far. You can view more entries at a time and navigate between entires much easier. I quite like how each entry takes you through kind of a ghosted version of the form itself, seeing exactly what someone entered:

The Files Manager is a brand new thing! Wufoo forms can collect files easily, so if that's a thing you use, it might be mighty handy for you to be able to browse and manage those from the manager.

Those are great improvements for you for getting around and doing stuff within Wufoo, but of course, the most important thing is that you can build powerful forms very easily on Wufoo and integrate them anywhere you need to.

The post New on Wufoo: Form Manager Beta, File Manager Beta, Entry Manager Beta appeared first on CSS-Tricks.

Categories: Web Technologies

Here’s how I recreated theory11’s login form — how would you do it?

CSS-Tricks - Wed, 08/08/2018 - 14:11

I ran across a super cool design for a login form over on the website theory11.com. Actually, the whole site and the products they make are incredibly well designed, there's just something about the clean and classy form that really got me. Plus, it just so happened that the CodePen Challenge that coming week was based on forms, so I took a few minutes and tried slapping it together.

Fadeout vector pattern

One of the things I thought was super classy was the way that vector wallpaper-eque pattern was not only there but faded out sort of radially. I didn't try to match the pattern exactly—I just grabbed one from the Assets Panel in CodePen and dropped it onto the <html> element as a SVG data URL background-image with a low fill-opacity. Then a radial gradient sits on top and creates the fading effect—a radial gradient with the same base background color that fades away.

:root { --gray: rgb(14, 19, 25); --gray--t: rgba(14, 19, 25, 0); } html { background: var(--gray) url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="28" height="49" viewBox="0 0 28 49"%3E%3Cg fill-rule="evenodd"%3E%3Cg id="hexagons" fill="%239C92AC" fill-opacity="0.1" fill-rule="nonzero"%3E%3Cpath d="M13.99 9.25l13 7.5v15l-13 7.5L1 31.75v-15l12.99-7.5zM3 17.9v12.7l10.99 6.34 11-6.35V17.9l-11-6.34L3 17.9zM0 15l12.98-7.5V0h-2v6.35L0 12.69v2.3zm0 18.5L12.98 41v8h-2v-6.85L0 35.81v-2.3zM15 0v7.5L27.99 15H28v-2.31h-.01L17 6.35V0h-2zm0 49v-8l12.99-7.5H28v2.31h-.01L17 42.15V49h-2z"/%3E%3C/g%3E%3C/g%3E%3C/svg%3E'); } body { margin: 0; height: 100vh; background: radial-gradient( ellipse at bottom center, var(--gray--t), var(--gray) 90% ); } Double border

If you peek at the double border code on theory11's site, you'll see it's done with a single 2px solid border on a parent and another on the child element, with a bit of padding to space them out. Perfectly fine way to do it, of course. But it reminded me of the fact that you can literally do double as a border style. You have very little control over the spacing, but hey, it's close!

form { border: 7px double #AA8B59; } What about them corner boxes?

I had fun building the rest of it out, but I stopped short of dealing with those corner boxes. I thought about it though! My first thought was psuedo elements, as those are wonderful little tools for adding extra flair without any extra HTML. Except... you only get two of those and we need four here. Turns out that's how they do it—they get four because they use both the parent and the child (to get the border).

Peter Schmalfeldt took a crack at doing it that way:

See the Pen theory11 sign in by Peter Schmalfeldt (@manifestinteractive) on CodePen.

Dan Wilson took an entirely different approach by doing it with multiple background gradients:

See the Pen theory11 sign in (add corner boxes with background gradients) by Dan Wilson (@danwilson) on CodePen.

Another possibility would have been border-image. I find use cases for border-image rather rare, and the syntax pretty hard to grok, but this is kind of the perfect situation for it. The property uses "9 slice scaling," so imagine an image being cut up like a tic-tac-toe board. Then each of those areas can repeat or stretch (or variations of those). A graphic like this brown shape:

Nine-sliced:

And all those non-corner sections repeating directionally to make whatever middle space is needed.

SVG has similar potential. Mike Riethmuller has a great post about that. I'll steal his demo here:

See the Pen Flexy SVG by Chris Coyier (@chriscoyier) on CodePen.

See how different parts of that SVG stretch differently when the viewport is resized? I'm sure that could be used for our form design here as well.

I find it fun how many ways there are to do something like this. There's the ol' fashioned way, where those corners are just some <div>s you position and style up as needed. Or you could get extra super fancy and use Houdini / Paint API to do it!

The post Here’s how I recreated theory11’s login form — how would you do it? appeared first on CSS-Tricks.

Categories: Web Technologies

Chrome 69

CSS-Tricks - Wed, 08/08/2018 - 14:10

Chrome 69 is notable for us CSS developers:

  • Conic gradients (i.e. background: conic-gradient(red, green, blue);): We've got lots of interesting articles about conic gradients here, and here's some use cases and a polyfill from Lea Verou.
  • Logical box model properties: margin, padding, and border all get an upgrade for more use cases. Think of how we have margin-left now — the "left" part doesn't make much sense when we switch directions. Now, we'll have margin-inline-start for that. The full list is margin-{block,inline}-{start,end}, padding-{block,inline}-{start,end} and border-{block,inline}-{start,end}-{width,style,color}. Here's Rachel Andrew with Understanding Logical Properties And Values.
  • Scroll snap points (i.e. scroll-snap-type: x mandatory;): What once required JavaScript intervention is now happily in CSS. We've been covering this for years. Goes a long way in making carousels way less complicated.
  • Environment variables (i.e. env(safe-area-inset-top);): Apple introduced "the notch" with the iPhone X and dropped some proprietary CSS for dealing with it. The community quickly stepped in and now we have env() for browsers to ship stuff like this.

I guess we can give this version number a well-deserved nice.

Direct Link to ArticlePermalink

The post Chrome 69 appeared first on CSS-Tricks.

Categories: Web Technologies

Interview with Chris Rowe - Voices of the ElePHPant

Planet PHP - Wed, 08/08/2018 - 07:07

Show Notes Audio This episode is sponsored by .

The post Interview with Chris Rowe appeared first on Voices of the ElePHPant.

Categories: Web Technologies

Browser painting and considerations for web performance

CSS-Tricks - Wed, 08/08/2018 - 07:00

The process of a web browser turning HTML, CSS, and JavaScript into a finished visual representation is quite complex and involves a good bit of magic. Here’s a simplified set of steps the browser goes through:

  1. Browser creates the DOM and CSSOM.
  2. Browser creates the render tree, where the DOM and styles from the CSSOM are taken into account (display: none elements are avoided).
  3. Browser computes the geometry of the layout and its elements based on the render tree.
  4. Browser paints pixel by pixel to create the visual representation we see on the screen.

In this article, I'd like to focus on the last part: painting.

All of those steps combined is a lot of work for a browser to do on load... and actually, not just on load, but any time the DOM (or CSSOM) is changed. That’s why many web developers tend to partially solve this by using some sort of frontend framework, such as React which, apart from many other advantages, can help to highly optimize changes in the DOM to avoid unnecessary recalculating or rendering.

You may have heard terms such as state, component rendering, or immutability. All of those have something to do with the optimization of DOM changes, or in other words, to only make changes to the DOM when it's necessary.

To give an example, the state of a web application may change, and that would lead to a change in UI. However, certain (or many) components are not affected by this change. What React helps to do is limit the writing to the DOM for elements that are actually affected by a change in state and ultimately limit the rendering to the smallest part of the web application possible:

DOM/CSSOM → render tree → layout → painting

However, browser painting is special in its own way, as it can happen even without any changes to the DOM and/or CSSOM.

Example of page performance summary

The diagram above was generated using Chrome's performance panel in DevTools (more on that later) and it shows how much time was taken by each task in the browser in the recorded time (0-7.12s) after reloading of a page. As you can see, painting takes a significant part, and that's not automatically a bad thing. In this particular example, the increased painting is caused by a combination of animated GIFs on the page and canvas drawing (at 60fps), where both don't cause any changes to the DOM or its styles, while still triggering painting.

Another good example of a feature that may cause painting without any outside intervention is the CSS animation property, and compared to animated GIF or canvas, it is probably more common on the web. An animation is usually triggered by user input, like hover, but thanks to animation and @keyframes rules, we can even create quite complex animations running constantly on the page without much of an effort, which is pretty amazing.

What some might not realize, is that those animations can easily get out of hand and constantly trigger painting, and that can cost us a lot of processing power. Of course, there are some rules that can be used to avoid painting. Most obvious is limiting manipulation of elements to CSS transform and opacity properties, which by default don't trigger paint, unless some special circumstances are in place, such as animating an SVG path.

Paint flashing

You likely know that Chrome has DevTools. What you might not know about is a little shortcut (Shift+Cmd+P on Mac or Control+Shift+P on PC) which can be used inside DevTools to bring up a little search bar and command menu.

Command Menu

I've started digging around it, and apart from many other useful and incredibly interesting options, a render panel caught my attention.

Render Panel

At the first sight, you can see some interesting options that can be very helpful when it comes to debugging animation on the web, like an FPS meter.

FPS meter

Layer borders and paint flashing are also interesting tools. Layer borders are used to display the borders of layers as they are rendered by the browser so that any transformation or change in size is easily recognizable. Paint flashing serves to highlight areas of the webpage where the browser is forced to repaint.

Paint flashing

After discovering paint flashing, the first thing I did was check it out on a project of mine. In most places, there was no trouble. For instance, any movement triggered by scroll on the website was powered by the CSS transform property, which as we covered, doesn't cause painting. The painting was present where one would expect it to be, like changes in text color on hover, but that's not something that should be much of a concern due to its area and presence only on hover of the element. To sum it up, you can always find something to improve, even if you wrote the code yesterday…

But one thing was a slap in the face.

It doesn't matter how experienced or careful you are, you can — and most likely will — make a mistake. We're just people and some would argue that fixing your own bugs is most of the job when it comes to development. However, for a bug to be fixable, we need to be aware of it… and that's exactly where the render panel helps.

Case study

Let's take a closer look at the actual issue. The design came in with the request for a noisy background. That kind of effect that old TVs had when there was no signal.

It is known that GIFs have many issues, where performance is certainly one of them, so I definitely couldn't use that for a whole page background. If you'd like to read some more on why to avoid GIFs, here is a good resource with a bunch of reasons.

Using JavaScript is definitely an option in this case. Displaying or hiding elements with a slightly moved background was the first thing that came to my mind, and using canvas could help too. However, all of this seemed a little overkill for simply having a background. I decided to go for a CSS-only approach.

My solution was to take a small “noisy” PNG image as a background-image, enable background-repeat and throw it over a one-color background. How did I achieve the noise effect? With infinite CSS animation! By setting the background-position to different value over the period of 200 milliseconds. Here's how that turned out:

See the Pen MXoddr by Georgy Marchuk (@gmrchk) on CodePen.

Can you guess the problem? It seemed like a quite an elegant solution to me, and I was excited about my achievement of making it through without a crappy GIF and even not a single line of JavaScript. Just simple CSS that is optimized in browsers these days.

Well, the paint flashing showed something completely different. The layer of the size of the window was constantly repainting, without the user even doing anything. You can see the paint flashing in the demo above if you enable it in the render panel (note that paint flashing doesn't show up in embedded pen).

Without paint flashing (left) vs. with paint flashing (right)

That certainly doesn't play well with the performance of the website and drains laptop batteries like there's no tomorrow.

CPU usage for the animation done with background-position (top) and transform (bottom)

All of this CPU usage could have been avoided by replacing the changes to background-position using transform or opacity.

See the Pen XYOYGm by Georgy Marchuk (@gmrchk) on CodePen.

The problem

I've been doing web development for a while and I knew very well that animating a background is never a good idea. This felt like a rookie mistake. People make mistakes... but that's not the whole story. The website was all laggy and uncomfortable to navigate. How did I miss it?

Something that certainly plays a big role is the fact that I am (and you may be as well) a little spoiled when it comes to development equipment. I have a nice, powerful computer for work and access to speedy internet. Unless we write some really crappy code, anything we write runs quite smoothly in our eyes. But that's not always the case for our users.

A similar problem applies to many other things — like display size. Using a little exaggeration, while we are developing on 27” display with 4K resolution and getting the designs primarily for 1920x1080, our visitors come in mainly from 1366x768 laptops and have a completely different workflow when it comes to using a computer.

Conclusion

While this article started off as a piece about painting, its main topic is really much more about being mindful of the impact our code has on the painting process or performance in general. While painting serves as a good example of something that can be problematic and easily missed, it's more of a disconnect between developer and user that is the issue.

The web is a place of many environments, where the developer's environment is often far different than the user's. While there is no need to change our ways or switch to lazy computers, it definitely helps to see our work the way it is seen by others from time to time. My suggestion is: when you come home from work and have a little free time, try to pick up your old computer and check your work there, to get a little closer to what your users experience.

If you don't have this kind of computer around, tools like render panel can turn out to be awfully handy.

The post Browser painting and considerations for web performance appeared first on CSS-Tricks.

Categories: Web Technologies

205 Reset Content - Evert Pot

Planet PHP - Tue, 08/07/2018 - 08:00

205 Reset Content is somewhat similar to 204 No Content. It’s especially meant for hypertext applications.

Imagine if a user is filling in a html form, and this form gets submitted to the server.

If the server sends back a 204, a browser could act on this by telling the user the form submission was successful and NOT refresh the page.

If the server sent back a 205, a browser can reset the form, similar to a a reset button a html form:

<input type="reset" />

Browsers could implement this, but at least according to an article from 2008 by Ben Ramsey, they don’t. Implementing this status by a HATEOAS client could definitely still make sense though.

Example response:

HTTP/1.1 205 Reset Content Server: foo-bar/1.2 Connection: close References
Categories: Web Technologies

Short note on the accessibility of styled form controls

CSS-Tricks - Mon, 08/06/2018 - 11:13

Styling and accessibility are often at odds with each other. Scott O'Hara has this repo that shows how the two can work really well together in the context of form controls.

The trade-offs between native and styled controls reminds me of Eric Bailey's case study on focus styles:

A common misconception is that the focus style can only use the outline property. It’s worth noting that :focus is a selector like any other, meaning that it accepts the full range of CSS properties. I like to play with background color, underlining, and other techniques that don’t adjust the component’s current size, so as to not shift page layout when the selector is activated.

The nice thing about Scott's repo is that it serves as a baseline that can be pulled into a project and customized from there. Sort of like WTF, forms? but with a clear—ahem—focus on accessibility. Styles are considered, but less the point.

While we're on the topic, let's not let Dave Rupert's "Nutrition Cards for Accessible Components" go unnoticed. It also shipped recently and—aside from being a clever idea—is a truly useful thing to reference the accessibility expectations of specific components. Definitely worth a bookmark. &#x1f516;

Direct Link to ArticlePermalink

The post Short note on the accessibility of styled form controls appeared first on CSS-Tricks.

Categories: Web Technologies

Pages