Character Details

The first component I worked on was the Character Details section of the character sheet. It is the bit at the top where you put your name and fill the more generic descriptions of your character. Race, class, name, eye colour, etc.

As simple as it looks (and is), it took me a very long time to get it working right. Why? Is it not just text next to the logo?

Well... It was before I accepted the fact that sometimes you want to use flexbox, other times you want to use CSS Grids. I was also trying to not have media queries. I have this OCD-like thing of trying to have as little code as possible. As wonderful as it sounds, at certain level, it is detrimental. I spend too much time rattling my brain trying to find a way to do away with industry standard ways of doing certain things simply because I feel it could be done with less code. (spoiler alert: More often than not I am wrong). There is a ton of talented people out there who know what they are doing.

There is a reason why an industry standard is an industry standard. It's because the majority of people agree that's the best current solution.

Note the current there. Times change, standards change. Make sure you are up to date with standards and make sure you embrace change. Holding on to tradition for the sake of tradition has a history of being detrimental to everybody.

Anyway, enough with the philosophical rant. Once I realized Flex was the technique to use, the rest fell into place.

The reason flex is the tool for this job, is because flex elements do not have to align in the same tracks when wrapping into new lines or rows. While with CSS grid, each element will sit within its designed row/column track so the gaps between all child elements will always align.


The second component I tackled was the attributes. This one has a little bit of JavaScript logic in it as I wanted to test calculating the bonus derived by the attribute itself. Those bonus are quite important as they are used in many sections of the character sheet. When it comes to building the whole sheet as one piece, I will probably need to change how I am storing this data so all components can access it.

On this component I used CSS grid. The way the data is structured and needs to be displayed makes it perfect for it. The total opposite to the character details above.

Saving Throws

This component posed an interesting challenge when viewed in the mobile. In the source character sheet one can see that the saving throws are organized in a neat table, with some labels on top. No different than the attributes except, that the saving throws table is much wider than the attributes one. The attributes component did fit quite nicely and snugly on a mobile screen, the saving throws didn't.

To get around that issue on small screens, I decided to only show the saving throw name, the total modifier and the temporary modifier. We need the name and the total for obvious reasons and the temporary because it is the one that is likely to be changing frequently. No values can be changed currently as all I am focusing on at the moment is adapting the layout to work on different screen resolutions.

I also move the location of the conditional modifiers box according to the size of the screen for better use of the space.


Next down on the character sheet would be Base Attack Bonus, Spell Resistance and Grapple but I'll quickly skip those smaller sections to go over the larger one. Later on I'll go over them all.

Here's the Attack component I made. At one point I intent to also have a printable version of this sheet(to-do: get the link once ready) so I will have to work out how to render more copies of this component, even if empty, in order to fill the front of the sheet as it is in the paper version. For now, in the digital version, I will only be rendering the component if there is data to display.

Layout wise, there isn't anything different from the previous components. If anything, I am getting better as this didn't feel hard to think and plan. I am using a flex container for info/details of the attack type and CSS grid for the ammunition.

Speaking of the ammunition, it posed an interesting question as how to handle it. In the paper version, we have a maximum ammunition load, with space to write some extra notes and some thirty checkboxes for the player to keep track of how many has been used.

Using Vue was rather trivial to create the checkboxes, with a default of thirty disabled checkboxes rendered if no ammunition present (for presentation's sake), and hook them up to the total ammunition. Now if one is to tick a checkbox, the ammunition count decreases accordingly. Adding the notes next to the ammunition amount was also trivial. Finally, a little bit of conditional rendering and Array manipulation with the checkedBoxes yields a very convenient reset button for all checkboxes.


Skills may not look it but it is a rather complicated component when you break it down to the individual parts it is made of. It pulls in data from several points - The character attributes, class, level, race, user input... For now we won't be tackling any of that. Let us only set the layout and leave all skills in. Later on, when building the whole sheet, we will have an easier access to all different data sources and will be able to put it all together.

Even when focusing only on the CSS layout, there is still plenty of details to consider when styling this component.

First, refer again to the source character sheet. Right out of the bat we can see there is a plenty of information crammed there. No biggie when on desktop or large tablets. Mobiles: a different kettle of fish.

As a whole, this component follows the same mix-and-match CSS Grid and Flexbox party that has been going on so far with some notable points.

The heading proved an interesting challenge that I, initially, thought I would not be able to overcome. Except that I did, and was actually super simple. The name of the component SKILLS is to be placed in the middle of the horizontal axis of the whole component. Given the fact that the Max ranks box sits to the right of it, I puzzled over how to calculate its position for hours without success. Only the following morning, while washing the dishes, it occurred to me that all I needed was a dummy element to the left of the SKILLS word to make it happen. Flex it horizontally and make each take a third of the space then, on mobile, flex is vertically. Duh!

When I started tackling this layout, I had the labels part of the component display as flexbox and the skills list as CSS grid. They would not line up no matter how much I cursed at it. Eventually I got the point they had to be styled using the same set of rules. So I created a skills-columns class, applied to the relevant elements, and the issue went away.

Finally, To accommodate for the lack of real screen estate in the mobile view, I am hiding some of the non-critical columns to free up some space in order to the remaining columns be readable. That allows this component to be as little as 280 pixels wide and still be readable. I have also removed some elements that are present in the paper version as it was causing far more headaches than the benefits they would bring had I left them in.

Miscellaneous Components

By now, I am starting to get a bit sharp with this CSS grid and Flexbox. Things make a bit more sense and these components are becoming easier to style.

Worth of note in this defences component is how I am setting a couple of the grid items to span more than one tracks and making sure the HP and AC headers both start in the very first column in all screens.

Some of the other components can be grouped up nicely as one single set for simplicity sake.

Same here, we group a few more little components together and, at last, we are done with the front page of the character sheet.

Phew. That took some time. Several days working on and off. I write this here because if you have read this far you deserve to know that it wasn't easy. I did struggle plenty and gone back several times to refactor the code, tidy it up and so on. I hope this goes and inspires others not to give up and to let you, dear reader, know that you should persevere, work on your problem, it takes time but you will get there.

As for me. I carry on. This is only step one of four...


While working on this components, I have come across text-overflow: elipse. Very handy when you have long words and not enough space. The gotcha with this property is that it does not work on flex-children or grid-elements so, one has to convert the actual node containing the text into a block (or inline-block) element.

Lots of this text have been re-written after publishing. And probably will be re-written again.

  1. Prologue
  2. Chapter I - The first sprint
  3. Chapter II - Front Page Components
  4. Chapter III - Back Page Components

2,782 0 5