Do I still need this?

I know, I know. Minimalism isn’t exactly all the hype anymore. You all threw out all your shit years ago, when I was still hoarding things like a maniac. Minimalism isn’t even my goal to be honest and I don’t think I’ll ever be a true minimalist.

I guess it would be more appropriate to call me a maximalist by nature. A hunter and gatherer. My brain seems to be hard wired to come up with new ideas, start new projects and collect things. I cannot count how many lists I have. Lists of things. And even lists of lists of things.

And I’m terrible at finishing things, and at letting things go. Especially the things that I started and that I’m still interested in, which apparently is a big, broad range of things. Combine this with (at least) some signs of ADHS/ADS and the focus of a toddler, and guess what? Not the best combination for your mental hygiene and productivity.

But I digress. If the last quarter of 2020 taught me anything about life, it’s that nothing lasts forever, and that some of my habits weren’t very sustainable at all. So I kinda, sorta unintentionally made this the motto for my new year:

Do I still need this?

  • What are the chances, that I eventually really read this PDF that sat in my download directory for the past three years now?
  • When was the last time I actually used this little whatever-it-is that still sits on my desk?
  • Do I really care about the opinions of this one crazy distant-friend-on-facebook who thinks Covid is a hoax and Bill Gates eats babies for breakfast?
  • Does this little habit and that tiny pattern I picked up really get me anywhere, anymore? Or could it be replaced with something better.
  • Do I really still need all of this?

There’s only so much time. And there’s plenty of books waiting on my bookshelf I am actually looking forward to read. So many projects that actually need my attention. Friends I haven’t talked to in a while and enjoy talking to. And – last but not least – my little family with two pretty cool kids to raise.

Ideas are plenty. The good one’s will stick, no matter me hoarding them. This year is dedicated to my attention, it’s time to let go of a few things.

Bring it on, 2021! I’m ready.

PS:
To make this post complete, here’s some of the things I got rid of and changes I made:
delete the facebook app
mute a few people on facebook
delete swarm and a bunch of other apps
throw out some stuff at home
no alcohol on weekdays
read more books
use twitter way more active and concious (instead of passively consuming)
– sell some old electronic stuff (e. g. my SLR equipment)
– finally digitize some old videos I found, including recordings of my late father and of a seven year old me embarassingly singing into the camera in pijamas (some things need to be preserved for posterity)

PPS:
This is not intended to be some “I set my goals in public to make me stick to it” post. I’m pretty positive that I will break some if not most of the things above in a heartbeat, and that’s fine. But it reminds me that a little change from time to time is a very good thing!

SVG charts without JavaScript – Part 2

In the first post, we built a simple chart from scratch using nothing but raw SVG code. While this was a good starting point, the hover interaction was still far from perfect and needs improvement to be really usable.

As we first used a <title> element for the tooltips, the hover interaction felt unresponsive and slow. Also they couldn’t really be styled the way I wanted. So, let’s scrap the title elements and see if there’s a better way to go about this.

What’s the goal?

The solution that I had in mind, was to make the whole chart hoverable, from top to bottom. This way you could glance over the whole chart very quickly to check the values from particular data points.

For comparism, here’s the example from the first post again, on the left, compared to what we’re trying to accomplish, on the right:

(Hover/tap to see the difference in action)

50 70 50 60 40 40

Example from Part 1

50 70 50 60 40

Goal of this post

To get there, we basically need to achieve two things:

  1. Control/enlarge the hover area to spread from top to bottom of the chart
  2. Find a way to show/hide the appropriate information (circle and number on the top right), on hover.

Thought process

I had several ideas on how this could possibly be built. Most of them didn’t work for various reasons. For the sake of documentation, here’s my thought process. (If you just want the solution, you can skip this part)

First thought: Add some padding around the circles 👎
Maybe by adding some padding around the <circle> elements we could enlarge the hover area to make it more usable. But SVG doesn’t seem to specify anything like padding, and different browsers interpret it very differently (if at all). So this was out the window very quickly.

Second thought: Pseudo-elements to the rescue 👎
If we could add a :before pseudo-element on the <circle> and position it accordingly we should be able to exactly control the hover area. As I learned, SVG elements are seen by browsers as replaced elements, like images, which are not allowed to have generated content, like pseudo-elements. Therefore, no :before or :after on SVG elements. Next!

Third thought: Style the wrapping <g> group element 👎
Change the size and position of the <g> group element that wraps each of our <circle> elements. As with the padding, I learned that container, or structural elements in SVG (like the <g> group element is) are not meant to be drawn/styled directly. So again, no luck with this one.

Fourth thought: Add HTML inside the SVGs? 👎
Maybe it is possible to add HTML code inside of the SVG code, somehow? A few google searches and some stackoverflow answers later, I learned about the <foreignObject> element in SVG. A few first tests and a quick check of the browser support (pretty good, except IE) I felt confident enough to give it a try, but after a few tests I realized that the browsers’ interpretations are unpredictable at best, which is why I threw this out as well.

Fifth thought: Adding invisible <rect> elements as hover areas 🥳
After all of the above failed (and me nearly giving up), I had another look at what some of the charting libraries out there do, and some of them make use of additional <rect> rectangle elements to act as invisible hover areas. This, combined with a little bit of CSS-trickery to hide and show the appropriate meta information, was exactly what I needed, works across browsers and is therefore what I ended up using.

Hover areas

As hover elements we add an additional <rect> element for each data point. This allows us to exactly control where the chart is hoverable and to control the display of additional meta information (like the number value on the top right).

So, for each data point, we end up with something like this:

<rect class="chart__hover" x="..." y="0" width="..." height="100%" />
<g class="chart__data">
    <circle class="chart__circle" cx="..." cy="..." r="2" />
</g>

Here’s the example of the end-goal again, with those hoverable areas highlighted in red:

(Hover/tap to see it in action)

50 70 50 60 40

By default – when nothing is hovered – I wanted the chart to display the last circle and number value, which is done by the following two lines of CSS. We use a group <g> element with class .chart__data for all the additional information. The first line sets all of them invisible (opacity: 0), the second line sets the last of them back to be visible.

.chart__data {
    opacity: 0;
}

.chart__data:last-of-type() {
    opacity: 1;
}

Show/hide information on hover

Now that we built our default state, we need to take care of what happens on hover.

To control this, we make us of the general sibling selector ~ and the adjacent sibling selector + in CSS. If used properly, those two can work like magic.

An example will show much better what they do than words could. In our example a hover over <rect class="chart__hover"> should control the display of the following <g class="chart__data">. As those are direct – aka “adjacent” – siblings, we can use the adjacent sibling selector + like so:

.chart__hover:hover + .chart__data {
    opacity: 1;
}

While this works, it also still shows the initial (last) value and circle. Luckily, there’s also a general sibling selector ~ which selects every sibling element that comes after the element we selected. So, to make every .chart__data invisible that comes after the hovered .chart__hover, we can add:

.chart__hover:hover ~ .chart__data {
    opacity: 0;
}

The combination of those two statements do all the work to show the appropriate meta data on hover.

Because we’ve put everything inside a group it’s also very easy to add additional data on hover, if needed.

As you can see, this makes for a pretty neat effect and an intuitive way of interacting with the chart, all without any JS to this point.

To further enhance this, you would probably still want to use JavaScript. Things like updating data on the fly, changing the range of the data shown without reloading the whole page each time. Stuff like this would all be viable options to use JS and for more sophisticated charts there certainly is a time and place for full-fletched data visualization frameworks like d3.js, Highcharts.js and others. But if the only thing you want to do is painting a simple line-chart, maybe a solution like this could be faster and easier to maintain than loading the whole kitchen sink.

I hope this shows how far we can take a design by utilizing native, widely supported browser features. And all of this without the need to download and parse anything more than some HTML/SVG markup and a few CSS styles.

In the next post I will quickly glance over the function I used to dynamically generate this SVG code from a given array of data.

SVG charts without JavaScript – Part 1

I recently needed to visualize some rather simple data in a chart. After playing around with a few ideas, I ended up generating the plain SVG code from the data, without using any frameworks or even JavaScript. In these posts I’d like to share some of the things I learned.

My initial thought was to just throw a fancy JavaScript library at it, let it do the work and call it a day. Because that’s what the cool kids do nowadays, right? But doing it this ways would have added yet another dependency to our project as well as making us dependant on JavaScript being loaded in the first place, just to see the chart. While I’m perfectly fine with using JavaScript to progressively enhance things, I believe we should strive to provide the basic functionality without it.

Also, it was a perfect opportunity for me to learn a bit more about SVG, which would have been useful, even if this didn’t turned out the way I wanted.

After reading this post by Rich Harris about how he built charts for the New York Times using plain SVG I started to think that maybe I could do it in a similar way.

Lets get started!

NOTE: To follow the code examples, you should have a basic understanding of how SVG works. I won’t go into much detail about the basics of SVG in general, as there are plenty of good tutorials out there already.

What I wanted to achieve

Here’s one of the early sketches of what I wanted the chart to look like in the end:

40

Pretty straight forward, right?

Apart from the <svg> element itself, which acts as our “artboard” if you will, the chart can be broken down into the following parts:

<polygon>
.chart__area

<polyline>
.chart__line

<circle>
.chart__circle

# #

<text>
.chart__text

  1. a path for the background fill area
  2. a path for the line
  3. a circle for each of the data points
  4. a text element in the top right, to display the number value of the last point

In our SVG code, we end up with something like this:

<svg class="chart" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <polygon class="chart__area" points="..." />
    <polyline class="chart__line" points="..." />
    <circle class="chart__circle" cx="..." cy="..." r="..." />
    ...
    <circle class="chart__circle" cx="..." cy="..." r="..." />
    <text class="chart__text" x="75" y="0">#</text>
</svg>

Now, to make those elements actually paint something, we need to feed them some data. (Later on we’ll generate this dynamically, but for the sake of readability let’s do it manually now.)

We use an SVG with a 100 x 100 viewBox to make calculations easier, and we use the following five data points: 50, 30, 40, 50, 60.

<svg class="chart" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <polygon class="chart__area" points="0,50 25,30 50,50 75,40 100,60 100,100 0,100 />
    <polyline class="chart__line" points="0,50 25,30 50,50 75,40 100,60" />
    <circle class="chart__circle" cx="0" cy="50" r="2" />
    <circle class="chart__circle" cx="25" cy="30" r="2" />
    <circle class="chart__circle" cx="50" cy="50" r="2" />
    <circle class="chart__circle" cx="75" cy="40" r="2" />
    <circle class="chart__circle" cx="100" cy="60" r="2" />
    <text class="chart__text" x="75" y="0">40</text>
</svg>

For the background fill path (.chart__area), we add some additional points at 100 100 and 0 100 to go around the bottom and close the path.

Next we set a stroke color and stroke-width to make the paths visible. This could be written right into the SVG, but I prefer to keep the styling to CSS.

.chart__area {
    fill: #fee9c0;
}

.chart__line {
    stroke: #efa216;
    stroke-width: 1px;
}

.chart__circle {
    stroke: #efa216;
    stroke-width: 1px;
    fill: #fafbff;
}

.chart__text {
    font-size: .7em;
    fill: #efa216;
}

This already comes pretty close to what I wanted to achieve.

But at this point, I realized that the chart started to look very crowded when adding more than just the few points from my initial sketch. While we likely won’t have thousands of them in this project, I wanted the design to be able to handle this scenario as well (it’s always a good idea to have the “Just in Case Mindset” when designing).

My first idea was to hide the circles, and only display them on hover, by adding the following CSS.

.chart__circle {
    stroke: #ccc;
    stroke-width: 1px;
    opacity: 0;
}

.chart__circle:hover {
    opacity: 1;
}
40
40

As you can see in those examples, hiding the circles and revealing them on hover (hover over the line in the second example above to see the effect in action) looks pretty good already and even gives it a touch of interactivity. But I missed two things:

  • the hover interaction doesn’t feel very smooth because the hoverable area is only exactly over the circle itself
  • to quickly see the number value of a point when hovering, I wanted to display the number on the top right of the chart, when a point is hovered

Some of you might say: This is the point were JavaScript comes into play! Sure, sure, it could. But maybe there’s a way we can achieve this with just native browser features.

First thing I found, is that there is a <title> element (not an attribute) in SVG, which will render the same way on hover as we are used to from a title attribute. To make this work with our circles, we’d need to group the <circle> in a <g> element and put a <title> element afterwards with the value inside.

<svg class="chart" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
    <polygon class="chart__area" points="0,50 25,30 50,50 75,40 100,60 100,100 0,100 />
    <polyline class="chart__line" points="0,50 25,30 50,50 75,40 100,60" />
    <g>
        <circle class="chart__circle" cx="0" cy="50" r="2" />
        <title>50</title>
    </g>
    <g>
        <circle class="chart__circle" cx="25" cy="30" r="2" />
        <title>70</title>
    </g>
    <g>
        <circle class="chart__circle" cx="50" cy="50" r="2" />
        <title>50</title>
    </g>
    <g>
        <circle class="chart__circle" cx="75" cy="40" r="2" />
        <title>60</title>
    </g>
    <g>
        <circle class="chart__circle" cx="100" cy="60" r="2" />
        <title>40</title>
    </g>
    <text class="chart__text" x="75" y="0">40</text>
</svg>

Et voilà: If you hover over the line and wait for a second, you should see the title in action. Not perfect, but it works and it gives us the number value on hover.

50 70 50 60 40 40

So far, we built a basic chart by using only plain SVG and a little bit of CSS. We even added a bit of interactivity with the hover effect.

At this point, I maybe became a little bit obsessed with this whole idea of building the whole chart including as much of the interactivity as possible without JavaScript.

Of course if we want to update or re-render data, we will still use JavaScript to enhance this later on. But for the first initial rendering and some basic interactivity? Maybe not as much as I thought.

Next step will be to find out how far we can take the interactivity, which I’ll cover in the next post.

Wrap a Gutenberg Block in a container element

If you use a Gutenberg Block, it can sometimes be useful to wrap them in a container element to further control the styling.

In my case I wanted to wrap the core HTML block in a div with custom CSS class “block-html”.

WordPress 5.0 introduces an easy way to change the output of Gutenberg Blocks by using render_block – and without touching any JavaScript at all.

/**
 * Wrap Gutenberg block with container element
 */

function wrap_my_block( $block_content, $block ) {

    if ( 'core/html' === $block['blockName'] ) {
        $block_content = '<div class="block-html">' . $block_content . '</div>';
    }

    return $block_content;

};

add_filter( 'render_block', 'wrap_my_block', 10, 2 );