The DOM Diet and Year Pickers

I think we all know that having a smaller DOM is good for performance but I was never sure what’s considered big or small, or at what points performance is affected. Knowing a little more can change how you approach things.

I was recently doing a performance analysis on some pages and the tool I chose to use was the Chrome Performance Audit. If you open Dev Tools (F12) and go to the Audits tab you’ll see a range of available audits which includes Performance. This uses a tool called Lighthouse and gives estimates for various performance metrics as well as Opportunities and Diagnostics.

One of the diagnostics which came up for me was “Uses an excessive DOM size” and the detail gives us this:

Browser engineers recommend pages contain fewer than ~1,500 DOM nodes. The sweet spot is a tree depth < 32 elements and fewer than 60 children/parent element. A large DOM can increase memory usage, cause longer style calculations, and produce costly layout reflows.

The item that triggered this diagnostic for me was a year picker, a select element with 150 options. Whilst I don’t think it’s really causing any major performance issues it did strike me that 1 parent element and 150 children does seem excessive for just picking out one number from a consecutive range so I started looking at alternative ways we could do this. I wanted to put my year picker on a  “DOM Diet”. I created this pen:

See the Pen Year Pickers by Chris Smith (@chris22smith) on CodePen.dark

Here’s a quick comparison of 4 possible ways of selecting a year from a consecutive range. It’s important to not only look at possible DOM performance but also the user experience side – ease of understanding and ease of use. No point making it faster if it’s confusing or hard work.

Select/Dropdown

This is the standard method. It can have a default value or a blank value as the first option. It’s very familiar, ease to understand and use. It’s probably better to start with a blank value so that we know a user has actually made a selection rather than just left the default. It supports arrow keys and mousewheel. It’s easy to validate using just the required property as the available options are set. It can look untidy in some browsers when long option lists run off the bottom of the screen and it does use a lot of DOM nodes.

Range Input

The input[type=range] doesn’t show a value by default so you have to do a bit of work to show an output value, and a bit more work to do this elegantly. Through testing I found the output value had to go above the slider rather than below so it was not obscured by a finger using the control. I think this is fairly easy to understand but users may not be aware that they can use their arrow keys to get greater precision – either up/down or left/right. It can be hard to control and get the exact figure you want dragging the handle especially using a finger. It can also be wired up to support the wheel event and respond to scrolling up or down on the mousewheel. There’s no way to have a blank value so it has to have a default set. There’s no real validation to be done as it has to use a value in the range. It’s very kind to the DOM too with only 3 nodes.

Number Input

This method is very simple. You just let the user type in the date they want. It can be left blank or have a default value. It can be controlled using arrow keys or the mousewheel though I’m not sure how many users know this. By setting the min, max and step attributes it can limit the range entered when not typing. If the value is typed (or pasted) it will require validation. This uses a single DOM node.

Multiple Number Inputs

This final method is just a bit of a “left field” design. The advantage of it is that it’s very easy to update using the tab key and arrow keys. By having the digits separated the range for each is only ever 10 so in theory it should mean less to change. If left blank it could be set to automatically shift the focus to the next input when a value is added. This makes it as fast to type the 4 digits as a single number input. The min, max and step attributes can limit the range for each digit. It’s light on the DOM too with only 5 nodes. The disadvantage with this method is the validation – it’s going to be a bit more involved, parsing the 4 digits as a single value to be checked and then highlighting the invalid digit(s) could be difficult. On a mobile device with a number pad it also means the pad flashing in and out quickly, which is not a great experience so it’s only really suitable for desktop use.

I’m not sure I’d necessarily go running from the standard dropdown but some of the other methods are certainly possibilities and help keep the DOM smaller.

500 Mile Challenge – Half Way

This year I set myself a challenge, to run 500 miles within the calendar year, 2017. I’m now about half way through the year so thought it was time for a quick update and review.

When exactly is the half way point of the year? With February being short it’s probably around the second of July. Near enough for this post anyway.

So, half way through the year and a touch over half the miles covered. Today, 3rd July, I’ve done 256.9 miles. I’m now in training for Cardiff Half Marathon at the start of October so will start doing longer distance runs and should hopefully pull comfortably ahead in the next couple of months.

It might not seem like the most difficult challenge, and in truth it probably isn’t, but having it there has made a big difference. There have been many times where I might have not bothered going out but the idea of falling behind in my miles has kept me going. It also helps keep it regular, rather than doing nothing for 3 months then going nuts it keeps it steady and means I never get too unfit.

I’m logging each run in Airtable and am using the API data in a CodePen project to plot it on a graph using Chart.js. You can see the chart here:
https://codepen.io/chris22smith/project/live/XLxYnX/

graph of runs vs target

Getting Feedback on Codepen Demos

At the software company where I work, we’ve started using Codepen as a way of producing interactive demos or prototype pages. It’s slowly replacing the use of static images or mock-ups. We’ve started sharing the URLs for these with customers to get their feedback on new features.

This could be done by sending them 2 URLs, one for the pen and one for the feedback form, but it’s not as good as being able to complete the form whilst viewing the demo content at the same time. I came up with a way of requesting feedback within the pen.

SurveyMonkey

I embedded a SurveyMonkey survey tracking script within the pen. I amended the pen design slightly to add a sidebar div and then added the SurveyMonkey embed JavaScript block within this, in the HTML pane of the pen. The script had to be here so that it rendered in the right place. I gave this sidebar a fixed width so that we could control how the survey contents appeared. We then had to write the survey in such a way that it didn’t require much screen width and that all questions would fit into a sensible minimum screen height. In short, we kept questions short, no lists of 10 radio buttons.

CrazyEgg

I decided to also embed CrazyEgg. If you don’t know it, it’s a tool that allows you to track mouse clicks. It’s a very useful way of knowing which parts of your screen get the most interaction. We added this script into the head content, within the HTML settings. This is a paid service but you can get a free trial for a short time.

Debug Mode

The 2 scripts seemed to get blocked when we tried using the pen in Editor or Full Screen modes but Debug mode, which runs the code as it is without any header or validation, worked like a dream. You need a PRO account to use this mode. Well worth it anyway in my view.

Feedback Ready

I’m now looking at building this out as a template ready for future feedback gathering.

Star Wars Mini Projects in Codepen

The Star Wars universe seems to be a bit of a recurring theme for me when experimenting with 3D modelling and animation in Codepen. Here are some pens and a bit of explanation of how they were made. Naturally the code is available by switching the view.

CSS 3D Tie Fighter Wireframe


See the Pen CSS 3D Tie Fighter Wireframe.
1

The Tie Fighter body is just made up of a number of circles, <div>s with border-radius:50% rotated using transform:rotateY(). See the pen CSS Sphere Wireframe to see this part in isolation. The front cockpit window circles are the same but brought forward using transform:translateZ(). The axle is actually just 2 flat rectangles. One is brought slightly forwards and the other is set slightly back using transform:translateZ(). The hexagonal wings were the most difficult part. The hexagons are made up of 3 rectangles rotated through 60 degrees. The inner triangles are then formed using pseudo elements inside these triangles which are rotated 30 degrees and have one border applied and the dimensions set just right. See the pen CSS Hexagon with inner triangles to see just this part. Finally, the whole thing, the .sphere, is rotated to show off the 3D. The blueprint style background is a combination of linear gradients and background sizing and positioning.

Tie Fighter Attack


See the Pen Tie Fighter Attack.
1

In this project the Tie Fighters are much simpler. Each one is actually just a letter H in a sans-serif font with a small circle (border-radius) over the centre of it. I use JavaScript to set a random position within the viewport, randomly scale and rotate each one slightly so they appear less uniform. The movement is just CSS. Each one uses a keyframe animation to increase it’s Z position using transform:translateZ(). So, it is generated, animated towards the viewer until the perspective means it’s out of sight and then removed from the DOM. I just keep doing this at regular intervals and it gives the appearance of lots of objects moving towards the viewer, just missing. Another effect at play here is the opacity. Each Tie Fighter starts off with 0 opacity and it increases to 1 as they approach giving the appearance of them coming out of a fog becoming clearer as they approach. The final effect is the shooting. A random proportion of the fighters shoot. These are assigned a class and then use a pseudo element to draw a tall thin box below the main fighter. This is invisible but has green box-shadow. This then uses a CSS animation to add a blink effect.

3D Death Star


See the Pen 3D Death Star.
1

This project uses a 3D sphere made up of rotated circles which rotates. It has one static circle inside it, which is achieved by rotating it in the opposite direction. This has a linear gradient to give it a three dimensional feel. The indented weapon part is just another circle placed on the surface with the gradient running in the opposite direction. The stars are positioned randomly using JavaScript and appear in 3 layers. These are rotated against the Death Star to give the impression of movement.

You can find lots of great pens in Marie Mosley‘s Star Wars collection.