We have an angularjs web site that has a single large SVG image as the background. Imagine that it is a picture of a forest with a windy path going through it. We would like to place graphical buttons along the path that the user can click on to go to the next screen.

The application is written so if you resize the browser, the SVG background will resize according to its aspect ratio. If the browser dimensions aren't in the same aspect ratio as the SVG, we still show the entire SVG in the correct aspect ratio, but we have a white border around the image to fill up the remaining area of the browser window.

The problem is: How do I put the graphical buttons on top of the SVG and make sure that they stay in the correct position as we resize? We don't want the buttons to drift off the path visually.

We believe we need to create the buttons outside of the SVG because we would like to have different graphical states for the button (available, unavailable, pressed, roll-over, etc). And likely the buttons need to use SVG graphics with the same aspect ratio as the background to scale as well? However, if there are other aspects of SVG that we don't know about that would help for this situation, we are open to anything.

We had a similar problem in the past, and we tried to position the buttons using css properties of left and top as percentages. This kind of works, but the buttons are moving around too much for our liking. We weren't using SVG graphics for the buttons with the same aspect ratio though...just PNG. Maybe that was the problem?

1 Answers

Ian On Best Solutions

If your container element (the block element which holds your SVG background and the buttons) is always the same aspect ratio, then from the sound of it, your best bet may be to use absolute positioning. If you position with top and right as percents, the button elements will always remain in the same relative position. If you want to position the buttons based on their centers, instead of their edges, you can also add a transform, like so:

Example: if you run this and resize the window, the button will always be in the same relative position in the container.

.container {
  /* Arbitrary - makes the container half the width of the parent */
  width: 75%;
  /* This preserves a 1:2 aspect ratio */
  padding-top: 50%;
  /* This is necessary for children to have position: absolute */
  position: relative;
  /* Replace this with your SVG */
  background: lightblue;

button {
  position: absolute;
  /* Makes the top be 1/4 of the height of the container away from the container top, always */
  top: 25%;
  /* Same but for left */
  left: 25%;
  /* Pulls the button back half its height and half its width so it's positioned based on its center, not its top-left corner. */
  transform: translate(-50%, -50%);
<div class="container">
<button>Button Text</button>