Tag: Inline

Inline SVG… Cached

I wrote that using inline <svg> icons makes for the best icon system. I still think that’s true. It’s the easiest possible way to drop an icon onto a page. No network request, perfectly styleable.

But inlining code has some drawbacks, one of which is that it doesn’t take advantage of caching. You’re making the browser read and process the same code over and over as you browse around. Not that big of a deal. There are much bigger performance fish to fry, right? But it’s still fun to think about more efficient patterns.

Scott Jehl wrote that just because you inline something doesn’t mean you can’t cache it. Let’s see if Scott’s idea can extend to SVG icons.

Starting with inline SVG

Like this…

<!DOCTYPE html> <html lang="en">  <head>   <title>Inline SVG</title>   <link rel="stylesheet" href="/styles/style.css"> </head>  <body>    ...     <svg width="24" height="24" viewBox="0 0 24 24" class="icon icon-alarm" xmlns="http://www.w3.org/2000/svg">     <path id="icon-alarm" d="M11.5,22C11.64,22 11.77,22 11.9,21.96C12.55,21.82 13.09,21.38 13.34,20.78C13.44,20.54 13.5,20.27 13.5,20H9.5A2,2 0 0,0 11.5,22M18,10.5C18,7.43 15.86,4.86 13,4.18V3.5A1.5,1.5 0 0,0 11.5,2A1.5,1.5 0 0,0 10,3.5V4.18C7.13,4.86 5,7.43 5,10.5V16L3,18V19H20V18L18,16M19.97,10H21.97C21.82,6.79 20.24,3.97 17.85,2.15L16.42,3.58C18.46,5 19.82,7.35 19.97,10M6.58,3.58L5.15,2.15C2.76,3.97 1.18,6.79 1,10H3C3.18,7.35 4.54,5 6.58,3.58Z"></path>   </svg>

It’s weirdly easy to toss text into browser cache as a file

In the above HTML, the selector .icon-alarm will fetch us the entire chunk of <svg> for that icon.

const iconHTML = document.querySelector(".icon-alarm").outerHTML;

Then we can plunk it into the browser’s cache like this:

if ("caches" in window) {   caches.open('static').then(function(cache) {     cache.put("/icons/icon-wheelchair.svg", new Response(       iconHTML,       { headers: {'Content-Type': 'image/svg+xml'} }     ));   } }

See the file path /icons/icon-wheelchair.svg? That’s kinda just made up. But it really will be put in the cache at that location.

Let’s make sure the browser grabs that file out of the cache when it’s requested

We’ll register a Service Worker on our pages:

if (navigator.serviceWorker) {      navigator.serviceWorker.register('/sw.js', {     scope: '/'   }); }

The service worker itself will be quite small, just a cache matcher:

self.addEventListener("fetch", event => {   let request = event.request;    event.respondWith(     caches.match(request).then(response => {       return response || fetch(request);     })   ); });

But… we never request that file, because our icons are inline.

True. But what if other pages benefitted from that cache? For example, an SVG icon could be placed on the page like this:

<svg class="icon">   <use xlink:href="/icons/icon-alarm.svg#icon-alarm" />  </svg>

Since /icons/icon-alarm.svg is sitting there ready in cache, the browser will happily pluck it out of cache and display it.

(I was kind of amazed this works. Edge doesn’t like <use> elements that link to files, but that’ll be over soon enough.)

And even if the file isn’t in the cache, assuming we actually chuck this file on the file system likely the result of some kind of “include” (I used Nunjucks on the demo).

But… <use> and inline SVG aren’t quite the same

True. What I like about the above is that it’s making use of the cache and the icons should render close to immediately. And there are some things you can style this way — for example, setting the fill on the parent icon should go through the shadow DOM that the <use> creates and colorize the SVG elements within.

Still, it’s not the same. The shadow DOM is a big barrier compared to inline SVG.

So, enhance them! We could asynchronously load a script that finds each SVG icon, Ajaxs for the SVG it needs, and replaces the <use> stuff…

const icons = document.querySelectorAll("svg.icon");  icons.forEach(icon => {   const url = icon.querySelector("use").getAttribute("xlink:href"); // Might wanna look for href also   fetch(url)     .then(response => response.text())     .then(data => {       // This is probably a bit layout-thrashy. Someone smarter than me could probably fix that up.        // Replace the <svg><use></svg> with inline SVG       const newEl = document.createElement("span");       newEl.innerHTML = data;       icon.parentNode.replaceChild(newEl, icon);        // Remove the <span>s       const parent = newEl.parentNode;       while (newEl.firstChild) parent.insertBefore(newEl.firstChild, newEl);       parent.removeChild(newEl);     }); });

Now, assuming this JavaScript executes correctly, this page has inline SVG available just like the original page did.

Demo & Repo

, ,

Text Wrapping & Inline Pseudo Elements

I love posts like this. It’s just about adding a little icon to the end of certain links, but it ends up touching on a million things along the way. I think this is an example of why some people find front-end fun and some people rather dislike it.

Things involved:

  1. Cool [attribute] selectors that identify off-site links
  2. Deliberating on whether it’s OK to use additional HTML within links or not
  3. Usage of white-space
  4. Combining margin-left and padding-right to place icons into placeholder space
  5. Using custom properties to keep things easier
  6. Usage of inline SVG versus background SVG
  7. Considering inline versus inline-block
  8. Using masks

Direct Link to ArticlePermalink

The post Text Wrapping & Inline Pseudo Elements appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Multi-Line Inline Gradient

Came across this thread:

My first thought process was:

But it turns out we need a litttttle extra trickery to make it happen.

If a solid color is fine, then some padding combined with box-decoration-break should get the basic framework:

See the Pen Multiline Padding with box-decoration-break by Chris Coyier (@chriscoyier) on CodePen.

But a gradient on there is gonna get weird on multiple lines:

See the Pen Multiline Padding with box-decoration-break by Chris Coyier (@chriscoyier) on CodePen.

I’m gonna credit Matthias Ott, from that thread, with what looks like the perfect answer to me:

See the Pen Multiline background gradient with mix-blend-mode by Matthias Ott (@matthiasott) on CodePen.

The trick there is to set up the padded multi-line background just how you want it with pure white text and a black background. Then, a pseudo-element is set over the whole area with the gradient in the black area. Throw in mix-blend-mode: lighten; to make the gradient only appear on the black area. Nice one.

The post Multi-Line Inline Gradient appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Accessible SVG Icons With Inline Sprites

This is a great look at accessible SVG markup patterns by Marco Hengstenberg. Here’s the ideal example:

<button type="button">   Menu   <svg class="svg-icon"      role="img"      height="10"      width="10"      viewBox="0 0 10 10"      aria-hidden="true"      focusable="false">      <path d="m1 7h8v2h-8zm0-3h8v2h-8zm0-3h8v2h-8z"/>     </svg> </button>

Notes:

  • It’s not the <svg> itself that is interactive — it’s wrapped in a <button> for that.
  • The .svg-icon class has some nice trickery, like em-based sizing to match the size of the text it’s next to, and currentColor to match the color.
  • Since real text is next to it, the icon can be safely ignored via aria-hidden="true". If you need an icon-only button, you can wrap that text in an accessibily-friendly .visually-hidden class.
  • The focusable="false" attribute solves an IE 11 bug.

Plus a handy Pen to reference all the patterns.

Direct Link to ArticlePermalink

The post Accessible SVG Icons With Inline Sprites appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]