Archiwum kategorii: CSS

Simple Patterns for Separation (Better Than Color Alone)

Post pobrano z: Simple Patterns for Separation (Better Than Color Alone)

Color is pretty good for separating things. That’s what your basic pie chart is, isn’t it? You tell the slices apart by color. With enough color contrast, you might be OK, but you might be even better off (particularly where accessibility is concerned) using patterns, or a combination.

Patrick Dillon tackled the Pie Chart thing

Enhancing Charts With SVG Patterns:

When one of the slices is filled with something more than color, it’s easier to figure out [who the Independents are]:

See the Pen Political Party Affiliation – #2 by Patrick Dillon (@pdillon) on CodePen.

Filling a pie slice with a pattern is not a common charting library feature (yet), but if your library of choice is SVG-based, you are free to implement SVG patterns.

As in, literally a <pattern /> in SVG!

Here’s a simple one for horizontal lines:

<pattern 
    id="horzLines" 
    width="8" 
    height="4" 
    patternUnits="userSpaceOnUse">
       <line 
          x1="0" 
          y1="0" 
          x2="8" 
          y2="0" 
         style="stroke:#999;stroke-width:1.5" 
       />
</pattern>

Now any SVG element can use that pattern as a fill. Even strokes. Here’s an example of mixed usage of two simple patterns:

See the Pen Simple Line Patterns by Chris Coyier (@chriscoyier) on CodePen.

That’s nice for filling SVG elements, but what about HTML elements?

Irene Ros created Pattern Fills that are SVG based, but usable in CSS also.

Using SVG Patterns as Fills:

There are several ways to use Pattern Fills:

  • You can use the patterns.css file that contains all the current patterns. That will only work for non-SVG elements.

  • You can use individual patterns, but copying them from the sample pages. CSS class definitions can be found here and SVG pattern defs can be found here

  • You can add your own patterns or modify mine! The conversion process from SVG document to pattern is very tedious. The purpose of the pattern fills toolchain is to simplify this process. You can clone the repo, run npm install and grunt dev to get a local server going. After that, any changes or additions to the src/patterns/**/* files will be automatically picked up and will re-render the CSS file and the sample pages. If you make new patterns, send them over in a pull request!

Here’s me applying them to SVG elements (but could just as easily be applied to HTML elements):

See the Pen Practical Patterns by Chris Coyier (@chriscoyier) on CodePen.

The CSS usage is as base64 data URLs though, so once they are there they aren’t super duper manageable/changeable.

Here’s Irene with an old timey chart, using d3:

Managing an SVG pattern in CSS

If your URL encode the SVG just right, you and plop it right into CSS and have it remain fairly managable.

See the Pen Simple Line Patterns by Chris Coyier (@chriscoyier) on CodePen.

Other Examples Combining Color

Here’s one by John Schulz:

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

Ricardo Marimón has an example creating the pattern in d3. The pattern looks largely the same on the slices, but perhaps it’s a start to modify.

Other Pattern Sources

We rounded a bunch of them up recently!


Simple Patterns for Separation (Better Than Color Alone) is a post from CSS-Tricks

How to Disable Links

Post pobrano z: How to Disable Links

The topic of disabling links popped up at my work the other day. Somehow, a „disabled” anchor style was added to our typography styles last year when I wasn’t looking. There is a problem though: there is no real way to disable an <a> link (with a valid href attribute) in HTML. Not to mention, why would you even want to? Links are the basis of the web.

At a certain point, it looked like my co-workers were not going to accept this fact, so I started thinking of how this could be accomplished. Knowing that it would take a lot, I wanted to prove that it was not worth the effort and code to support such an unconventional interaction, but I feared that by showing it could be done they would ignore all my warnings and just use my example as proof that it was OK. This hasn’t quite shaken out for me yet, but I figured we could go through my research.

First, things first:

Just don’t do it.

A disabled link is not a link, it’s just text. You need to rethink your design if it calls for disabling a link.

Bootstrap has examples of applying the .disabled class to anchor tags, and I hate them for it. At least they mention that the class only provides a disabled style, but this is misleading. You need to do more than just make a link look disabled if you really want to disable it.

Surefire way: remove the href

If you have decided that you are going to ignore my warning and proceed with disabling a link, then removing the href attribute is the best way I know how.

Straight from the official Hyperlink spec:

The href attribute on a and area elements is not required; when those elements do not have href attributes they do not create hyperlinks.

An easier to understand definition from MDN:

This attribute may be omitted (as of HTML5) to create a placeholder link. A placeholder link resembles a traditional hyperlink, but does not lead anywhere.

Here is basic JavaScript code to set and remove the href attribute:

/* 
 * Use your preferred method of targeting a link
 *
 * document.getElementById('MyLink');
 * document.querySelector('.link-class');
 * document.querySelector('[href="https://unfetteredthoughts.net"]');
 */
// "Disable" link by removing the href property
link.href = '';
// Enable link by setting the href property
link.href = 'https://unfetteredthoughts.net';

Styling this via CSS is also pretty straightforward:

a {
  /* Disabled link styles */
}
a:link, a:visited { /* or a[href] */
  /* Enabled link styles */
}

That’s all you need to do!

That’s not enough, I want something more complex so that I can look smarter!

If you just absolutely have to over-engineer some extreme solution, here are some things to consider. Hopefully, you will take heed and recognize that what I am about to show you is not worth the effort.

First, we need to style our link so that it looks disabled.

.isDisabled {
  color: currentColor;
  cursor: not-allowed;
  opacity: 0.5;
  text-decoration: none;
}
<a class="isDisabled" href="https://unfetteredthoughts.net">Disabled Link</a>

Setting color to currentColor should reset the font color back to your normal, non-link text color. I am also setting the mouse cursor to not-allowed to display a nice indicator on hover that the normal action is not allowed. Already, we have left out non-mouse users that can’t hover, mainly touch and keyboard, so they won’t get this indication. Next the opacity is cut to half. According to WCAG, disabled elements do not need to meet color contrast guidelines. I think this is very risky since it’s basically plain text at this point, and dropping the opacity in half would make it very hard to read for users with low-vision, another reason I hate this. Lastly, the text decoration underline is removed as this is usually the best indicator something is a link. Now this looks like a disabled link!

But it’s not really disabled! A user can still click/tap on this link. I hear you screaming about pointer-events.

.isDisabled {
  ...
  pointer-events: none;
}

Ok, we are done! Disabled link accomplished! Except, it’s only really disabled for mouse users clicking and touch users tapping. What about browsers that don’t support pointer-events? According to caniuse, this is not supported for Opera Mini and IE<11. IE11 and Edge actually don't support pointer-events unless display is set to block or inline-block. Also, setting pointer-events to none overwrites our nice not-allowed cursor, so now mouse users will not get that additional visual indication that the link is disabled. This is already starting to fall apart. Now we have to change our markup and CSS…

.isDisabled {
  cursor: not-allowed;
  opacity: 0.5;
}
.isDisabled > a {
  color: currentColor;
  display: inline-block;  /* For IE11/ MS Edge bug */
  pointer-events: none;
  text-decoration: none;
}
<span class="isDisabled"><a href="https://unfetteredthoughts.net">Disabled Link</a></span>

Wrapping the link in a <span> and adding the isDisabled class gives us half of our disabled visual style. A nice side-affect here is that the disabled class is now generic and can be used on other elements, like buttons and form elements. The actual anchor tag now has the pointer-events and text-decoration set to none.

What about keyboard users? Keyboard users will use the ENTER key to activate links. pointer-events are only for pointers, there is no keyboard-events. We also need to prevent activation for older browsers that don’t support pointer-events. Now we have to introduce some JavaScript.

Bring in the JavaScript

// After using preferred method to target link
link.addEventListener('click', function (event) {
  if (this.parentElement.classList.contains('isDisabled')) {
    event.preventDefault();
  }
});

Now our link looks disabled and does not respond to activation via clicks, taps, and the ENTER key. But we are still not done! Screen reader users have no way of knowing that this link is disabled. We need to describe this link as being disabled. The disabled attribute is not valid on links, but we can use aria-disabled="true".

<span class="isDisabled"><a href="https://unfetteredthoughts.net" aria-disabled="true">Disabled Link</a></span>

Now I am going to take this opportunity to style the link based on the aria-disabled attribute. I like using ARIA attributes as hooks for CSS because having improperly styled elements is an indicator that important accessibility is missing.

.isDisabled {
  cursor: not-allowed;
  opacity: 0.5;
}
a[aria-disabled="true"] {
  color: currentColor;
  display: inline-block;  /* For IE11/ MS Edge bug */
  pointer-events: none;
  text-decoration: none;
}

Now our links look disabled, act disabled, and are described as disabled.

Unfortunately, even though the link is described as disabled, some screen readers (JAWS) will still announce this as clickable. It does that for any element that has a click listener. This is because of developer tendency to make non-interactive elements like div and span as pseudo-interactive elements with a simple listener. Nothing we can do about that here. Everything we have done to remove any indication that this is a link is foiled by the assistive technology we were trying to fool, ironically because we have tried to fool it before.

But what if we moved the listener to the body?

document.body.addEventListener('click', function (event) {
  // filter out clicks on any other elements
  if (event.target.nodeName == 'A' && event.target.getAttribute('aria-disabled') == 'true') {
    event.preventDefault();
  }
});

Are we done? Well, not really. At some point we will need to enable these links so we need to add additional code that will toggle this state/behavior.

function disableLink(link) {
// 1. Add isDisabled class to parent span
  link.parentElement.classList.add('isDisabled');
// 2. Store href so we can add it later
  link.setAttribute('data-href', link.href);
// 3. Remove href
  link.href = '';
// 4. Set aria-disabled to 'true'
  link.setAttribute('aria-disabled', 'true');
}
function enableLink(link) {
// 1. Remove 'isDisabled' class from parent span
  link.parentElement.classList.remove('isDisabled');
// 2. Set href
  link.href = link.getAttribute('data-href');
// 3. Remove 'aria-disabled', better than setting to false
  link.removeAttribute('aria-disabled');
}

That’s it. We now have a disabled link that is visually, functionally, and semantically disabled for all users. It only took 10 lines of CSS, 15 lines of JavaScript (including 1 listener on the body), and 2 HTML elements.

Seriously folks, just don’t do it.


How to Disable Links is a post from CSS-Tricks

4 Reasons to Go PRO on CodePen

Post pobrano z: 4 Reasons to Go PRO on CodePen

I could probably list about 100 reasons, since as a founder, user, and (ahem) PRO member of CodePen myself, I’m motivated to do so. But let me just list a few here. Some of these are my favorites, some are what PRO members have told us are their favorite, and some are lesser-known but very awesome.

1) No-hassle Debug View

Debug View is a way to look at your the Pen you’ve built with zero CodePen UI around it and no <iframe> containing it. Raw output! That’s a dangerous thing, in the world of user-generated code. It could be highly abused if we let it go unchecked. The way it works is fairly simple.

You can use Debug View if :

  1. You’re logged in
  2. The Pen is PRO-owned

Logging in isn’t too big of a deal, but sometimes that’s a pain if you just wanna shoot over a Debug View URL to your phone or to CrossBrowserTesting or something. If you’re PRO, you don’t worry about it at all, Debug View is totally unlocked for your Pens.

2) Collab with anybody anytime

Collab Mode on CodePen is the one that’s like Google Docs: people can work together in real time on the same Pen. You type, they see you type, they type, you see what they type.

Here’s what is special about that:

  • There is nothing to install or set up, just shoot anybody a link.
  • Only you need to be PRO. Nobody else does. They don’t even have to be logged in.

Basically, you can be coding together with someone (or just one or the other of you watching, if you please) in about 2 seconds. Here’s a short silent video if you wanna see:

People use it for all sorts of things. In classrooms and educational contexts, for hiring interviews, and just for working out problems with people across the globe.

Drag and drop uploading

Need to quickly host an asset (like an image) somewhere? As in, quickly get a URL for it that you can use and count on forever? It’s as easy as can be on CodePen.

If you’re working on a Project, you can drag and drop files right into the sidebar as well:

Save Anything Privately

Privacy is unlimited on CodePen. If you’re PRO, you can make unlimited Private Pens and Private Collections. You’re only limited in Private Projects by the total number of Projects on your plan. This is the number one PRO feature on CodePen for a variety of reasons. People use them to keep client work safe. People use them to experiment without anyone seeing messy tidbits. People use them to keep in-progress ideas.


I didn’t even mention my actual favorite CodePen PRO feature. I’ll have to share that one some other time 😉

Go PRO on CodePen


4 Reasons to Go PRO on CodePen is a post from CSS-Tricks

SVG as a Placeholder

Post pobrano z: SVG as a Placeholder

It wasn’t long ago when Mikael Ainalem’s Pen demonstrated how you might use SVG outlines in HTML then lazyload the image (later turned into a webpack loader by Emil Tholin). It’s kind of like a skeleton screen, in that it gives the user a hint of what’s coming. Or the blur up technique, which loads a very small image blurrily blown up as the placeholder image.

José M. Pérez documents those, plus some more basic options (nothing, an image placeholder, or a solid color), and best of all, a very clever new idea using Primitive (of which there is a mac app and JavaScript version), which creates overlapping SVG shapes to use as the placeholder image. Probably a bit bigger-in-size than some of the other techniques, but still much smaller than a high res JPG!

Direct Link to ArticlePermalink


SVG as a Placeholder is a post from CSS-Tricks

Robust React User Interfaces with Finite State Machines

Post pobrano z: Robust React User Interfaces with Finite State Machines

User interfaces can be expressed by two things:

  1. The state of the UI
  2. Actions that can change that state

From credit card payment devices and gas pump screens to the software that your company creates, user interfaces react to the actions of the user and other sources and change their state accordingly. This concept isn’t just limited to technology, it’s a fundamental part of how everything works:

For every action, there is an equal and opposite reaction.

– Isaac Newton

This is a concept we can apply to developing better user interfaces, but before we go there, I want you to try something. Consider a photo gallery interface with this user interaction flow:

  1. Show a search input and a search button that allows the user to search for photos
  2. When the search button is clicked, fetch photos with the search term from Flickr
  3. Display the search results in a grid of small sized photos
  4. When a photo is clicked/tapped, show the full size photo
  5. When a full-sized photo is clicked/tapped again, go back to the gallery view

Now think about how you would develop it. Maybe even try programming it in React. I’ll wait; I’m just an article. I’m not going anywhere.

Finished? Awesome! That wasn’t too difficult, right? Now think about the following scenarios that you might have forgotten:

  • What if the user clicks the search button repeatedly?
  • What if the user wants to cancel the search while it’s in-flight?
  • Is the search button disabled while searching?
  • What if the user mischievously enables the disabled button?
  • Is there any indication that the results are loading?
  • What happens if there’s an error? Can the user retry the search?
  • What if the user searches and then clicks a photo? What should happen?

These are just some of the potential problems that can arise during planning, development, or testing. Few things are worse in software development than thinking that you’ve covered every possible use case, and then discovering (or receiving) new edge cases that will further complicate your code once you account for them. It’s especially difficult to jump into a pre-existing project where all of these use cases are undocumented, but instead hidden in spaghetti code and left for you to decipher.

Stating the obvious

What if we could determine all possible UI states that can result from all possible actions performed on each state? And what if we can visualize these states, actions, and transitions between states? Designers intuitively do this, in what are called „user flows” (or „UX Flows”), to depict what the next state of the UI should be depending on the user interaction.

Picture credit: Simplified Checkout Process by Michael Pons

In computer science terms, there is a computational model called finite automata, or „finite state machines” (FSM), that can express the same type of information. That is, they describe which state comes next when an action is performed on the current state. Just like user flows, these finite state machines can be visualized in a clear and unambiguous way. For example, here is the state transition diagram describing the FSM of a traffic light:

What is a finite state machine?

A state machine is a useful way of modeling behavior in an application: for every action, there is a reaction in the form of a state change. There’s 5 parts to a classical finite state machine:

  1. A set of states (e.g., idle, loading, success, error, etc.)
  2. A set of actions (e.g., SEARCH, CANCEL, SELECT_PHOTO, etc.)
  3. An initial state (e.g., idle)
  4. A transition function (e.g., transition('idle', 'SEARCH') == 'loading')
  5. Final states (which don’t apply to this article.)

Deterministic finite state machines (which is what we’ll be dealing with) have some constraints, as well:

  • There are a finite number of possible states
  • There are a finite number of possible actions (these are the „finite” parts)
  • The application can only be in one of these states at a time
  • Given a currentState and an action, the transition function must always return the same nextState (this is the „deterministic” part)

Representing finite state machines

A finite state machine can be represented as a mapping from a state to its „transitions”, where each transition is an action and the nextState that follows that action. This mapping is just a plain JavaScript object.

Let’s consider an American traffic light example, one of the simplest FSM examples. Assume we start on green, then transition to yellow after some TIMER, and then RED after another TIMER, and then back to green after another TIMER:

const machine = {
  green: { TIMER: 'yellow' },
  yellow: { TIMER: 'red' },
  red: { TIMER: 'green' }
};
const initialState = 'green';

A transition function answers the question:

Given the current state and an action, what will the next state be?

With our setup, transitioning to the next state based on an action (in this case, TIMER) is just a look-up of the currentState and action in the machine object, since:

  • machine[currentState] gives us the next action mapping, e.g.: machine['green'] == {TIMER: 'yellow'}
  • machine[currentState][action] gives us the next state from the action, e.g.: machine['green']['TIMER'] == 'yellow':
// ...
function transition(currentState, action) {
  return machine[currentState][action];
}

transition('green', 'TIMER');
// => 'yellow'

Instead of using if/else or switch statements to determine the next state, e.g., if (currentState === 'green') return 'yellow';, we moved all of that logic into a plain JavaScript object that can be serialized into JSON. That’s a strategy that will pay off greatly in terms of testing, visualization, reuse, analysis, flexibility, and configurability.

See the Pen Simple finite state machine example by David Khourshid (@davidkpiano) on CodePen.

Finite State Machines in React

Taking a look at a more complicated example, let’s see how we can represent our gallery app using a finite state machine. The app can be in one of several states:

  • start – the initial search page view
  • loading – search results fetching view
  • error – search failed view
  • gallery – successful search results view
  • photo – detailed single photo view

And several actions can be performed, either by the user or the app itself:

  • SEARCH – user clicks the „search” button
  • SEARCH_SUCCESS – search succeeded with the queried photos
  • SEARCH_FAILURE – search failed due to an error
  • CANCEL_SEARCH – user clicks the „cancel search” button
  • SELECT_PHOTO – user clicks a photo in the gallery
  • EXIT_PHOTO – user clicks to exit the detailed photo view

The best way to visualize how these states and actions come together, at first, is with two very powerful tools: pencil and paper. Draw arrows between the states, and label the arrows with actions that cause transitions between the states:

We can now represent these transitions in an object, just like in the traffic light example:

const galleryMachine = {
  start: {
    SEARCH: 'loading'
  },
  loading: {
    SEARCH_SUCCESS: 'gallery',
    SEARCH_FAILURE: 'error',
    CANCEL_SEARCH: 'gallery'
  },
  error: {
    SEARCH: 'loading'
  },
  gallery: {
    SEARCH: 'loading',
    SELECT_PHOTO: 'photo'
  },
  photo: {
    EXIT_PHOTO: 'gallery'
  }
};

const initialState = 'start';

Now let’s see how we can incorporate this finite state machine configuration and the transition function into our gallery app. In the App‚s component state, there will be a single property that will indicate the current finite state, gallery:

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      gallery: 'start', // initial finite state
      query: '',
      items: []
    };
  }
  // ...

The transition function will be a method of this App class, so that we can retrieve the current finite state:

  // ...
  transition(action) {
    const currentGalleryState = this.state.gallery;
    const nextGalleryState =
      galleryMachine[currentGalleryState][action.type];

    if (nextGalleryState) {
      const nextState = this.command(nextGalleryState, action);

      this.setState({
        gallery: nextGalleryState,
        ...nextState // extended state
      });
    }
  }
  // ...

This looks similar to the previously described transition(currentState, action) function, with a few differences:

  • The action is an object with a type property that specifies the string action type, e.g., type: 'SEARCH'
  • Only the action is passed in since we can retrieve the current finite state from this.state.gallery
  • The entire app state will be updated with the next finite state, i.e., nextGalleryState, as well as any extended state (nextState) that results from executing a command based on the next state and action payload (see the „Executing commands” section)

Executing commands

When a state change occurs, „side effects” (or „commands” as we’ll refer to them) might be executed. For example, when a user clicks the „Search” button and a 'SEARCH' action is emitted, the state will transition to 'loading', and an async Flickr search should be executed (otherwise, 'loading' would be a lie, and developers should never lie).

We can handle these side effects in a command(nextState, action) method that determines what to execute given the next finite state and action payload, as well as what the extended state should be:

  // ...
  command(nextState, action) {
    switch (nextState) {
      case 'loading':
        // execute the search command
        this.search(action.query);
        break;
      case 'gallery':
        if (action.items) {
          // update the state with the found items
          return { items: action.items };
        }
        break;
      case 'photo':
        if (action.item) {
          // update the state with the selected photo item
          return { photo: action.item };
        }
        break;
      default:
        break;
    }
  }
  // ...

Actions can have payloads other than the action’s type, which the app state might need to be updated with. For example, when a 'SEARCH' action succeeds, a 'SEARCH_SUCCESS' action can be emitted with the items from the search result:

    // ...
    fetchJsonp(
      `https://api.flickr.com/services/feeds/photos_public.gne?lang=en-us&format=json&tags=${encodedQuery}`,
      { jsonpCallback: 'jsoncallback' })
      .then(res => res.json())
      .then(data => {
        this.transition({ type: 'SEARCH_SUCCESS', items: data.items });
      })
      .catch(error => {
        this.transition({ type: 'SEARCH_FAILURE' });
      });
    // ...

The command() method above will immediately return any extended state (i.e., state other than the finite state) that this.state should be updated with in this.setState(...), along with the finite state change.

The final machine-controlled app

Since we’ve declaratively configured the finite state machine for the app, we can render the proper UI in a cleaner way by conditionally rendering based on the current finite state:

  // ...
  render() {
    const galleryState = this.state.gallery;

    return (
      <div className="ui-app" data-state={galleryState}>
        {this.renderForm(galleryState)}
        {this.renderGallery(galleryState)}
        {this.renderPhoto(galleryState)}
      </div>
    );
  }
  // ...

The final result:

See the Pen Gallery app with Finite State Machines by David Khourshid (@davidkpiano) on CodePen.

Finite state in CSS

You might have noticed data-state={galleryState} in the code above. By setting that data-attribute, we can conditionally style any part of our app using an attribute selector:

.ui-app {
  // ...
  
  &[data-state="start"] {
    justify-content: center;
  }
  
  &[data-state="loading"] {
    .ui-item {
      opacity: .5;
    }
  }
}

This is preferable to using className because you can enforce the constraint that only a single value at a time can be set for data-state, and the specificity is the same as using a class. Attribute selectors are also supported in most popular CSS-in-JS solutions.

Advantages and resources

Using finite state machines for describing the behavior of complex applications is nothing new. Traditionally, this was done with switch and goto statements, but by describing finite state machines as a declarative mapping between states, actions, and next states, you can use that data to visualize the state transitions:

Gallery app state transition diagram

Furthermore, using declarative finite state machines allows you to:

  • Store, share, and configure application logic anywhere – similar components, other apps, in databases, in other languages, etc.
  • Make collaboration easier with designers and project managers
  • Statically analyze and optimize state transitions, including states that are impossible to reach
  • Easily change application logic without fear
  • Automate integration tests

Conclusion and takeaways

Finite state machines are an abstraction for modeling the parts of your app that can be represented as finite states, and almost all apps have those parts. The FSM coding patterns presented in this article:

  • Can be used with any existing state management setup; e.g., Redux or MobX
  • Can be adapted to any framework (not just React), or no framework at all
  • Are not written in stone; the developer can adapt the patterns to their coding style
  • Are not applicable to every single situation or use-case

From now on, when you encounter „boolean flag” variables such as isLoaded or isSuccess, I encourage you to stop and think about how your app state can be modeled as a finite state machine instead. That way, you can refactor your app to represent state as state === 'loaded' or state === 'success', using enumerated states in place of boolean flags.

Resources

I gave a talk at React Rally 2017 about using finite automata and statecharts to create better user interfaces, if you want to learn more about the motivation and principles:

Slides: Infinitely Better UIs with Finite Automata

Here are some further resources:


Robust React User Interfaces with Finite State Machines is a post from CSS-Tricks

Discover The Fatwigoo

Post pobrano z: Discover The Fatwigoo

When you use a bit of inline <svg> and you don’t set height and width, but you do set a viewBox, that’s a fitwigoo. I love the name.

The problem with fatwigoo’s is that the <svg> will size itself like a block-level element, rendering enormously until the CSS comes in and (likely) has sizing rules to size it into place.

It’s one of those things where if you develop with pretty fast internet, you might not ever see it. But if you’re somewhere where the internet is slow or has high latency (or if you’re Karl Dubost and literally block CSS), you’ll probably see it all the time.

I was an offender before I learned how obnoxious this is. At first, it felt weird to size things in HTML rather than CSS. My solution now is generally to leave sensible defaults on inline SVG (probably icons) like height="20" width="20" and still do my actual sizing in CSS.

Direct Link to ArticlePermalink


Discover The Fatwigoo is a post from CSS-Tricks