Turning raster images into SVG files, one pixel at a time. Yes, really.
The PHP accepts a raster image (GIF, PNG, JPEG, that sort of thing) and creates an SVG image that recreates the raster image. It does this by drawing filled rectangles to recreate the pixels in the image. In many cases, this is literally a 1-by-1 rectangle, but it will check for runs of similar color (similar to GIF compression) and create one rectangle per run. It checks both horizontal and vertical runs to see which approach is more efficient, and returns the better option.
The script requires GD.
There are situations where people want to take small bitmaps—think primary-color buttons or badges—and make them scalable while still preserving their 8-bit appearance. See, for example, Joe Crawford’s post about upscaling a minitag. For those cases, this script will enable a quick conversion to SVG with at least some minimal attempts at optimization.
This all originally started as a one-off experiment and a bit of a jape. You can see the original at flaming-shame, if you fancy a laugh.
This is pretty neat: you can use
pointer-events: visiblePainted; to make only the filled (painted) part of an SVG respond to the pointer.
The quest for easy to implement concave corners on boxes is still ongoing, although there are some options open to us as the linked article explores.
I’m passionate about image performance optimisation and making images load fast on the web. One of the most interesting areas of exploration is placeholders: what to show when the image hasn’t loaded yet.
During the last days I have come across some loading techniques that use SVG, and I would like to describe them in this post.
Now browsers have audio. They have video. They even have WebGL and VR. And all those technologies work on mobile. The writing’s been on the wall for Flash for a while. Yet still, I’m sad to see it go. It was a brilliant crucible of creativity. A forge for many emerging artists in the field of creative coding, and many of the concepts from Flash and ActionScript were the proving grounds for their modern browser equivalents.
I’ll be looking back fondly on those years, rather than spitting on Flash’s grave. And as we see the last of the great browser plugins disappear* I hope you’ll join me in celebrating the creative culture that it nurtured.
We’ve been working with SVGs a lot recently, which has led our developers down a rabbithole of discovery! Here are some things to consider when it comes to SVGs and accessibility.
1. <img> tags and SVGs
When SVGs are implemented as <img> tags with an .svg as the source, we’ve encountered a few issues for VoiceOver and TalkBack users. These issues occur when those <img> tags don’t also have an ARIA role=”img” attribute.
2. <title> tags and SVGs
We often see examples of making SVGs accessible by simply adding a <title> element within the inline <svg>. While this does help in some situations, like a lone SVG icon within a link, adding a <title> element doesn’t make SVGs accessible in all browsing environments.
For example, when using Firefox and NVDA, a link containing an SVG would be recognized as a link, but the text within the <title> element would not be announced. NVDA announces the path within the href attribute only.
Adding an aria-labelledby attribute to the SVG can help expose the text within the <title> element to the browser’s accessibility API. However, even with this in place, NVDA does not announce the <title> text as we might expect.
Our most recommended approach when it comes to browser support and consistency across screen readers is to add a visually-hidden element as a sibling element to the <svg>. With this implementation, we’ve found that all browser and screen reader combinations tested were able to announce the link with the expected text announcement.
We also recommend adding aria-hidden=”true” to the <svg> element itself. This is to help prevent having any other text that may be embedded within the SVG be announced by screen readers. Then, the only text that should be announced would be the content within that visually-hidden element.
7. Colour contrast
While not a bug per se, we also see a lot of cases where designers and developers don’t plan for colour contrast issues for SVGs. Since SVGs function just like transparent GIFs in how they are displayed, different page background colors and effects can cause unanticipated issues for low vision users.
For example, a black SVG icon that’s perfectly visible with a white page background is going to be invisible in a Windows High Contrast theme that uses a black background. This is a common use case for users who use High Contrast settings due to light sensitivity or related issues. When you provide a solid background or contrasting border for SVGs, you can help avoid those kinds of problems.
A few days ago, I ran into a little problem when using SVGs. I’d created a reusable set of SVG symbols for a project I was working on, and started sprucing it up with all the pretty icons my designer gave to me. As we all know, one of the biggest benefits to using SVG is the “scalable” part of it, meaning that graphics render perfectly at and size, no matter the original size of the graphic. I’m a huge fan in general of SVG, and implementing them into this project was a no brainer for me.
However, a few of the icons in the design consisted of strokes, and those strokes were always 1px in width, no matter the size. When you scale an SVG, it scales everything about it, so an icon that’s scaled up two times would have stroke widths that are double the size of the original. One such example was a “+” icon that indicated there was more content. I had to reuse that icon at small and large sizes, but:
- I wanted the stroke width at all sizes to be 2px
- I wanted to create one graphic that I could reuse at any size without scaling the stroke width
Enter The Vector Effect Attribute
One of my favourite things about programming is being faced with a problem. It challenges you to research and find solutions. In this case, I stumbled upon the
vector-effectattribute, which conveniently has an available value called
non-scaling-stroke. It does exactly what it says, i.e. prevents strokes from scaling as an SVG scales.
I’d see a scaled up icon including scaled up effects. This one’s dimensions are 4 times the size of the original view box. As such, the stroke would render at 8px. In order to circumvent this, I added the
vector-effectattribute to the paths on the original graphic, and set the value to
non-scaling-stroke, like this:
Code language: HTML
This is really excellent: take a JPG, which has great compression for photos, but doesn’t support transparency, and link it within an
<svg> which can apply a clipping mask based on a path. The path can be traced manually over the photo in Photoshop or Illustrator, and can be exported as an SVG file from Illustrator. The following code (minus the path data), demonstrates how to do this:
Code language: HTML
<svg viewBox="0 0 921.17 1409.71">
<path d=" ... " />
<image xlink:href="/images/chris.jpg" clip-path="url(#chris-clip)" x="0" y="0" width="921" height="1409">
While working on some projects last year, we realized that if we had a more user-friendly, markup-based approach to configuring our SVG animations, we’d be more productive, and our clients could easily work with their own animations after hand-off as well. So we built an open-source tool!
LayerSnap is a script that builds on top of Snap SVG to build simple SVG animations by editing the SVG markup’s attributes. It comes with a suite of pre-set build transitions like “fade”, “move-down”, “enter-left”, “rotate-right”, etc. It also has an “anvil” transition, because no animation toolkit is complete without an anvil transition. These transitions can be configured via an attribute on every group (
g) element in an SVG, and a special syntax allows you to combine each transition with a host of configuration settings for their speed, delay, easing, looping, repeating, and even interactivity.
Demos, Docs, and more
- To get started with demos and documentation, check out the Layersnap project homepage
- The source code is on Github and NPM
- To file an issue for us to look at, or help us with a bug fix, please visit the issue tracker.