No Time Dad

A blog about web development written by a busy dad

Multiple SVG Background Images

Intro

A subntle background on a page can really make the content standout. The folks over at TailwindUI have a few hero sections that included background images, and it really makes the components look professional.

tailwind-dots

I haven’t tried including a background image on an element up until this point, so I thought it would be a fun project to work on. I liked how the example screenshot above has the background only on the left and right sides of the section. It does make the text pop, I think.

Building the element

My first pass at trying to build the TailwindUI version of the background was to dump the css properties background-color and background-image right into the Container selector. This, of course, did not work. The issue is that the svg is repeated across the entire element. I had a hunch this was going to happen, but I had to start somewhere. The patten I’ll be using for these examples is from heropatterns

Below is my initial css and html for this element. The html will be unchanged from this point on.

<div class="Container"></div>
.Container {
  background-color: #ffffff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='105' viewBox='0 0 80 105'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='death-star' fill='%23000000' fill-opacity='0.1'%3E%3Cpath d='M20 10a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm15 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zM20 75a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zm30-65a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm0 65a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zM35 10a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zM5 45a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zm60 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}

I needed to figure out how to only have the background show up on the left and right sides of the element. I read that background-repeat defaults to the value repeat, so I wondered if there were other values that might get me closer to my desired background.

After some digging around in the MDN docs, I found that there is a repeat-x value that background-repeat can take, which looks promising. It turns out that repeat-y is shorthand for repeat no-repeat. I added this to my existing Container selector to see how it would look.

.Container {
  background-color: #ffffff;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='105' viewBox='0 0 80 105'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='death-star' fill='%23000000' fill-opacity='0.1'%3E%3Cpath d='M20 10a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm15 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zM20 75a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zm30-65a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm0 65a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zM35 10a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zM5 45a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zm60 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
  /* Repeat the svg once on the y-axis only */
  background-repeat: repeat-y;
}

Halfway there. Now I need the svg on the right side of the div too. I knew from experience with box-shadow that some css properties can have multiple comma separated values. I was hoping this was the case with background-image too, which it turned out to be.

The issue with only adding multiple background images is that they’ll just stack on top of each other until I tell them where to go. After some googling, I found a property called background-position that takes a list of positions that can match a list of background images. If I had background-image: url("cats"), url("dogs");, I can then use background-position: left, right; which will put the cats on the left and dogs on the right.

.Container {
  background-color: #ffffff;
  /* Two of the same svg in a list */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='105' viewBox='0 0 80 105'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='death-star' fill='%23000000' fill-opacity='0.1'%3E%3Cpath d='M20 10a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm15 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zM20 75a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zm30-65a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm0 65a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zM35 10a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zM5 45a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zm60 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E"), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='105' viewBox='0 0 80 105'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='death-star' fill='%23000000' fill-opacity='0.1'%3E%3Cpath d='M20 10a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm15 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zM20 75a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zm30-65a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm0 65a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zM35 10a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zM5 45a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zm60 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
  background-repeat: repeat-y;
  /* The first svg goes on the left and the second svg goes on the right */
  background-position: left, right;
}

Now there’s one svg on the right and one on the left. It’s worth mentioning that I think there might be other ways to accomplish this without having two of the same SVGs in the background-image value. I spent some time tinkering with background-repeat values to try and achieve this, but I didn’t find a good soluition. The answer is out there somewhere, but I just couldn’t find it and I didn’t want to spend more time on it.

The other thing worth mentioning is that my version isn’t exactly like the TailwindUI version pictured above. Looking at their version, the svg background does not go all the up on the left and it does not go all the way down on the right. I spent some time trying to get this effect on my example, but I could not come up with a workable solution. I can’t see the html behind their version since it is paywalled, but I am thinking it might be a custom svg that has whitespace after the dots, or they’re clipping it somehow? Hard to say.

Where to go from here? Well, I think the first thing I’d do is turn down the svg opacity. The opacity value used above was for demonstration purposes to make the backgroud easier to see. Background images should be subtle for the most part, especially if they aren’t part of a feature or hero section on the page.

Below is a quick example of a hero section using this same svg background.

Grow your business today
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
.Container {
  background-color: white;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='105' viewBox='0 0 80 105'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='death-star' fill='%23000000' fill-opacity='0.03'%3E%3Cpath d='M20 10a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm15 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zM20 75a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zm30-65a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm0 65a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zM35 10a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zM5 45a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zm60 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E"), url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='105' viewBox='0 0 80 105'%3E%3Cg fill-rule='evenodd'%3E%3Cg id='death-star' fill='%23000000' fill-opacity='0.03'%3E%3Cpath d='M20 10a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm15 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zM20 75a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zm30-65a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V10zm0 65a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V75zM35 10a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zM5 45a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10zm60 35a5 5 0 0 1 10 0v50a5 5 0 0 1-10 0V45zm0-35a5 5 0 0 1 10 0v20a5 5 0 0 1-10 0V10z' /%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
  background-repeat: repeat-y;
  background-position: left, right;

  padding: 2rem;
}

.Header {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-top: 2rem;
  padding-bottom: 2rem;
}

.Header__Hero_Text {
  font-size: 36px;
  font-weight: 900;
}

.Text__Highlight {
  color: plum
}

.Header__Sub_Text {
  font-size: 18px;
  opacity: 0.8;
}

.Button {
  background-color: plum;
  border-color: plum;
  border-width: 1px;
  color: white;
  font-weight: 600;
  border-radius: 0.5rem;
  padding: 0.5rem 1rem;

}

.Button:hover {
  opacity: 0.8;
}

.Button:focus {
  outline: none;
  border-color: rgb(214, 70, 214);
  color: white;
  box-shadow: 0 0 0 0.2rem rgb(214, 70, 214, 0.25);
}
<div class="Container">
  <div class="Header">
    <div class="Header__Hero_Text">Grow your business <span class="Text__Highlight">today</span>
    </div>
    <div class="Header__Sub_Text">
      Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua
    </div>
  </div>
  <div class="Body">
    <button type="button" class="Button">Get Started</button>
  </div>
</div>

Overall, another fun project and good learning experience. Would I go out of my way to use a background image again? Maybe not, but I know how to get started with it if I ever wanted to.