Diagrams are great way to visualize large amounts of information into easy-to-understand formats. I recently had to create a diagram for our documentation and decided to do it using plain HTML with a CSS grid layout instead of images. This article demonstrates how you can create CSS diagrams that are performant, accessible, responsive, and easy to edit & style.

Here is a static image of the diagram:

Create Great Diagrams using CSS Grid Layouts

You can check out the HTML version of the diagram here. Try resizing the browser to see how the diagram automatically adapts to the screen size.

Why use HTML and CSS instead of images

Diagrams based on HTML and CSS have the following advantages:

  • Accessibility: If the diagram consists of plain DIV elements, it's automatically accessible. Screen readers and other assistive technologies can handle HTML beautifully. Your diagrams will be accessible to everyone, and no extra work is required on your part.
  • Responsiveness: Diagrams defined in HTML and CSS can adapt to different screen sizes automatically. No need for users to scroll horizontally and only see parts of the diagram at a time.
  • Easy Styling: If your diagrams are styled using CSS, it's easier to make them look like the rest of the page. If you decide to change the styles, like fonts and colors, the diagram will be updated automatically.
  • Easy Editing: If your diagrams are based on HTML, changing the text is a matter of editing the text on some HTML blocks. There’s no need to dig out the original application and document with the diagram, edit the document, and re-export it to a PNG or SVG file.
  • Clipboard Support: If your diagrams are based on HTML, people will be able to copy parts of it to get the original text. Of course, they can still take screenshots if they want to copy images.
  • Performance: Images are large! Even if you size if properly and use compressed formats, a very simple diagram image could be 30 to 50k in size, maybe a lot more. The same diagram in HTML/CSS is about 20% of the size and loads on the same request, so your app loads faster.

How to do create the diagram

The best way to create diagrams in HTML and CSS is to use CSS’s grid layout. It provides a two-dimensional grid that allows you to align elements to row and column ranges, with complete control over alignment, justification, and sizing.

CSS grids are available on all modern browsers, including Chrome, Firefox, and Edge. They can also be used in IE11, which supports an older spec. To use CSS grids in IE11, I suggest using an auto-prefixer such as Autoprefixer CSS online, which will add all the required prefixed/legacy CSS rules automatically for you.

Step 1: Sketch out the diagram

To create the diagram, start by sketching it out on a piece of paper or on a spreadsheet. This will make it easy to determine the row and column coordinates of each block.

This is an image of the Excel sheet I used:

Sketch out the diagram

Step 2: Create the HTML

Once you have the basic layout, create DIVs to represent each block. Give each DIV a unique class name or ID so you can style it later in CSS. You don’t have to worry too much about the content at this point, it will be easy to edit later if you have to.

This is the HTML for the diagram:

<div class="diagram" aria-label="Wijmo Olap Architecture Diagram">
    <div class="raw-data-client">
          Raw Data (client-side)
          Arrays with plain JavaScript objects.
    <div class="pivot-engine component">
          Summarizes the raw data according to views
          defined by fields and field lists
          (row, column, filter, and value lists).
    <!-- connectors -->
    <div class="conn row-2 col-4"> <!-- client data => engine -->
      <svg viewBox="0 0 10 10">
        <path d="M5 10 L1 5 L4 5 L4 -9 L6 -9 L6 5 L9 5z"/>

The HTML is simple. The DIVs have classes that will allow us to style each one. The only tricky part is the code that creates connecting arrows between the blocks. The code above shows how that was done. It uses an SVG element that draws an arrow pointing down. I also tried other approaches, including Unicode arrow characters, but SVG provides more flexibility and accurate positioning.

Step 3: Create the CSS for the grid

This is where we turn the plain text into a diagram.

The outer element has a “diagram” class which is the actual CSS grid, and is styled in CSS as follows:

.diagram {
    display: grid;
    grid-template-columns: repeat(14, 1fr);
    align-items: start;
    justify-items: center;
    max-width: 7in;
    margin: .2in 0;

The most important part is setting the “display” property to “grid.”

After that, the code uses the “grid-template-columns” CSS property to specify that the grid has 14 columns with equal width (“1fr” states that every column should be one “fractional unit” wide). This is not strictly required. If you remove that line, the grid layout will still work, but the columns will not have the exact same size.

Note that the code does not define any columns. Those will be created automatically by the browser and will be auto-sized by default.

The “align-items” property is set to “start” to ensure that the blocks will be auto-sized and aligned to the top of each cell. This is also optional. If you remove this setting, the blocks on each row will fill the row height, and there will be some black space at the bottom of most blocks.

Finally, the “max-width” and “margin” properties are set to ensure that the diagram doesn’t grow too wide and remains centered on the screen.

Step 4: Style the blocks

After that, the CSS uses a few generic rules that are applied to every block and to every block that represents a component. Those rules are not related to the CSS grid:

.diagram > div {
  padding: 12px;
  background: #EEE;
  border: 1px solid #C0C0C0;
.diagram > .component {
  border-radius: 12px;
  background: #E6E0FF;
  border: 2px solid #8E8EFF;

Step 4: Position the blocks within the grid

The most interesting parts are the rules that define the position of each block. For example, the code below defines the position of the “raw-data-client” and “pivot-engine” blocks.

.raw-data-client {
  grid-column: 1/span 5;
  grid-row: 1;
.pivot-engine {
  grid-column: 4/span 5;
  grid-row: 3;

The first block starts at column 1 and spans 5 columns. The second starts at column 4 and spans 5 columns as well. Both blocks have specific single rows.

These settings become clear if you refer to the spreadsheet that contains the layout sketch.

Step 5: Position and Style the SVG connectors

The connector elements use a slightly different approach. They have class names that specify the row and column where they should be rendered.

For example:

.row-2 {
  grid-row: 2;
.row-3 {
  grid-row: 3;
.col-4 {
  grid-column: 4;
.col-8 {
  grid-column: 8;

Finally, the CSS uses a couple of rules to scale and position the SVG connectors:

.diagram .conn {
  position: relative;
  width: .5in;
  height: .5in;
  padding: 0;
  border: none;
  background: transparent;
  z-index: -1;
.diagram .conn svg {
  position: absolute;
  width: 100%;
  height: 100%;
  overflow: visible;
  fill: #E6E0FF;

The connector elements have:

  • An outer DIV with relative positioning, fixed width and height, and a negative z-index to prevent the arrows from rendering above the blocks.
  • An inner SVG element that fills the cell but can overflow so the connector “spills” out of the cell and into any empty space above it.


And that’s all there is to it.

If you haven’t done so yet, check out the diagram here to see the result. Try resizing the browser to see how the diagram automatically adapts to the screen size.

I hope by now you agree that using HTML and CSS to create diagrams and infographics has significant benefits and can be a good alternative in some scenarios. I also hope you feel confident enough to give it a try in your future projects.

If you have questions suggestions about creating diagrams with HTML and CSS, please comment below.

Thank you in advance and happy coding!

Build lightweight, high-speed HTML5/JavaScript apps with zero dependencies

Try the latest version of Wijmo

Download Now!