question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support SVG symbols?

See original GitHub issue

I just realized that SVG symbols and inlined CSS are two very similar problems with very similar solutions. I wonder if styled-components can be made to handle SVG symbol management as well.

SVG symbols are very useful, they give you scalable icons that can be styled/colored with CSS, with low bandwidth use. To use them, there needs to be a symbol definition somewhere in the page, and then where you want to use it you put a <svg><use xlinkHref={iconId}/></svg>. The svg can be styled with CSS to change colors etc.

So how about something like

import ArrowSvg from '../icons/arrow.svg'

export const Arrow = styled.svgSymbol(ArrowSvg)`
  ${p => p.left && "transform: rotate(180deg);"}
  &:hover { fill: "yellow"; }
`

and later

<p><Arrow/> Styled-components is awesome! <Arrow left/></p>

which becomes this DOM:

<head><style>.a {...}.b{...}</style></head>
<body>
  <svg><symbol id="s">...</symbol></svg>
  <p>
    <svg class="a"><use xlink:href="#s"/></svg>
     Styled-components is awesome! 
    <svg class="b"><use xlink:href="#s"/></svg>
  </p>
</body>

So behind the scenes, styled-components would maintain the <svg/> block with the symbol definitions and come up with a global iconId for the <use/>. The ArrowSvg content could be from loading with https://github.com/jhamlet/svg-react-loader or something similar.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Reactions:3
  • Comments:14 (12 by maintainers)

github_iconTop GitHub Comments

12reactions
jaydensericcommented, Nov 16, 2017

These days IMO best way to handle SVG/icons is with react components:

const Icon = ({ size = '1em', color = 'currentColor', title, children }) => (
  <svg width={size} height={size} viewBox="0 0 32 32">
    <title>{title}</title>
    {children}
    <style jsx>{`
      svg {
        vertical-align: middle;
        fill: ${color};
      }
    `}</style>
  </svg>
)

export const MenuIcon = props => (
  <Icon title="Menu icon" {...props}>
    <path d="" />
  </Icon>
)

export const UserIcon = props => (
  <Icon title="User icon" {...props}>
    <path d="" />
  </Icon>
)

This way tree-shaking, code-splitting, etc. can ensure only the icons that are being used on a given view are downloaded.

You can then use props to configure any details of the icon (such as colors) on the fly.

Unlike with <use>, icons load instantly with the rest of the view from SSR.

<use> blinks terribly when anything causes your parent component to re-render, for example global header logos/icons when transitioning routes.

Your JSX linting can cover the SVGs.

Lots of benefits.

7reactions
jaydensericcommented, Nov 16, 2017

Huh, why does <use> blink?

Even when the SVG file is cached, anytime the surrounding DOM is manipulated/rerendered, the browser throws away the image and renders it all over again. This looks like a blink where for a few milliseconds the image collapses/becomes invisible, then displays again. If you use Next.js, and have a logo in a global header component in your page components, when routing between pages the browser re-renders the logo with a blink every transition.

Even if browsers optimized this behavior, SVG components will always look better when first loading a SSR page. They don’t load with a blink after the page displays like with <use>.

I don’t have a blinking demo handy sorry, because I refactored <use> to SVG components accross our site a few months ago.

if using full svg as react components, with SSR you might be shipping 50 copies of an SVG used for a bullet

True, but gzip handles repetition really well making it a non-issue.

1 “bullet”:

screen shot 2017-11-17 at 10 19 58 am

30 “bullets”:

screen shot 2017-11-17 at 10 19 37 am

If you are using <use> the traditional way, with a large-ish static icons.svg file pulled in globally only to use a few icons on the two pages a visitor views, there is more sent down the wire than if you just repeated a few inline SVGs (which often don’t repeat anyway).

At the end of the day, there are things you can do with SVG components you simply can’t with <use>, like dynamic content, animations and styles.

Read more comments on GitHub >

github_iconTop Results From Across the Web

<symbol> - SVG: Scalable Vector Graphics - MDN Web Docs
The <symbol> element is used to define graphical template objects which can be instantiated by a <use> element. The use of <symbol> elements...
Read more >
Support Icons – Download for Free in PNG and SVG - Icons8
Free Support icons in various UI design styles for web, mobile. Download static and animated Support vector icons for free in PNG, SVG,...
Read more >
71,752 Support Icons - Free in SVG, PNG, ICO - IconScout
Download 71752 Support Vector Icons for commercial and personal use. Available for free or premium in line, flat, gradient, isometric, glyph, sticker &...
Read more >
SVG Symbols | Font Awesome Docs
Plan to use the SVG+JS method of Font Awesome; Are using a lot of the same icon or icons on a single page;...
Read more >
SVG symbol a Good Choice for Icons - CSS-Tricks
Looking for a better way to do SVG icons? Inline SVG might be your best bet, which you can learn about in this...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found