The SVG element within Bootstrap 4, when using the viewBox attribute, does not always resize consistently

I am in the process of making my website design responsive, starting with the SVG logo. Following the excellent suggestions by Amelia Bellamy-Royds, I have included attributes for

viewBox,preserveAspectRatio, x, y, width
, and height.

I'm facing various challenges, but two are particularly puzzling:

1) As I resize my browser window, the navigation links disappear (even though the logo size remains constant), and beyond a certain breakpoint, the SVG grows significantly in size.

https://i.sstatic.net/8HhML.gif

Why does the svg scale so dramatically?

2) The current viewBox is set to viewBox="0 0 349 54". When I decrease these numbers to, say, 0 0 175 25, the image becomes larger. Conversely, increasing them, like changing it to 0 0 3500 540, makes the image smaller. However, there are instances when reducing the numbers results in a smaller size. How does altering these numbers arbitrarily affect the size of the svg?

Below is the relevant code for the navbar:

<nav class="navbar navbar-fixed-top navbar-dark bg-primary navbar-toggleable-md hidden-print"
     style="height:4em">
  <div class="row">
    <div class="col-md-2">
      <a class="navbar-brand"
         href="/">
        <svg viewBox="0 0 349 54"
             preserveAspectRatio="xMidYMid meet"
             x="0"
             y="0"
             width="100%"
             height="100%">
          <!-- SVG data goes here -->
        </svg>
      </a>
    </div>

    <div class="col-md-10">
      <button class="navbar-toggler navbar-inverse hidden-md-up navbar-toggler-left"
              type="button"
              data-toggle="collapse"
              data-target="#collapsingNavbar">
        ☰
      </button>

      <div class="collapse navbar-toggleable-md bg-primary"
           id="collapsingNavbar">
        <ul class="nav navbar-nav pull-right ml-auto">
          <li class="nav-item">
            <a class="nav-link"
               href="/home">
              <i class="fa fa-home"
                 aria-hidden="true"></i>
              Home
            </a>
          </li>

          [ ... ]

          <li class="nav-item">
            <a class="nav-link"
               href="/logout">
              <i class="fa fa-sign-out"
                 aria-hidden="true"></i>
              logout
            </a>
          </li>
        </ul>
      </div>  <!-- end collapsing navbar -->
    </div>  <!-- end col 10 -->
  </div>  <!-- end row -->
</nav>

Thank you for your assistance. Below is the pertinent CSS. These are all the selectors I have customized or added from the default bootstrap 4 alpha 6 release:

body {
  padding-top:6rem;
}

body, html {
  height:100%;
}

/* workaround modal-open padding issue */
body.modal-open {
    padding-right:0 !important;
}


#sidebar {
   padding-left:0;
}

.bg-primary {
  background-color: #001A57;
}

.top-buffer { margin-top:20px; }
.bottom-buffer { margin-bottom:.5rem; display: inline-block; }

/*
 * Off Canvas at medium breakpoint
 * --------------------------------------------------
 */
@media screen and (max-width: 48em) {

  .row-offcanvas {
    position: relative;
    -webkit-transition: all 0.25s ease-out;
    -moz-transition: all 0.25s ease-out;
    transition: all 0.25s ease-out;
  }

  .row-offcanvas-left
  .sidebar-offcanvas {
    left: -33%;
  }

  .row-offcanvas-left.active {
    left: 33%;
  }

  .sidebar-offcanvas {
    position: absolute;
    top: 0;
    width: 33%;
    height: 100%;
  }
}

/*
 * Off Canvas wider at sm breakpoint
 * --------------------------------------------------
 */
@media screen and (max-width: 34em) {
  .row-offcanvas-left
  .sidebar-offcanvas {
    left: -45%;
  }

  .row-offcanvas-left.active {
    left: 45%;
  }

  .sidebar-offcanvas {
    width: 45%;
  }
}


/* responsive nav stacked liked 3.x */
@media(max-width:34em) {
    .navbar .navbar-brand {
        float:none;
        display: block;
    }
    .navbar .navbar-nav>.nav-item {
        float: none;
        margin-left: .1rem;
    }
    .navbar .navbar-nav {
        float:none !important;
    }
}

svg {
  font: 10px sans-serif;
}

.navbar-toggler {
  -webkit-align-self: inherit;
      -ms-flex-item-align: inherit;
          align-self: inherit;
  padding: 0.25rem 0.75rem;
  font-size: 1.25rem;
  line-height: 1;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 0.25rem;
  position: absolute;
  right: 1em;
  top: .5em;
  color: white;
}

Answer №1

1) The reason your SVG becomes large is because you've instructed it to occupy the entire available space using width="100%". As the navbar collapses into the hamburger icon, it fills up the remaining space. Even without a width attribute, it would still fill that same space.

2) The viewBox establishes an independent user coordinate area, distinct from the viewport coordinate space where your SVG elements are rendered. It's important not to mistake viewBox values for setting actual dimensions for the SVG.

Initially, the user coordinate space matches the viewport coordinate space until you define specific values for viewBox, which then alter this relationship.

I like to think of the viewBox as a "window" into the SVG within the viewport coordinate space. The parameters for viewBox include x y width height. The first two values indicate where the viewBox starts in relation to the viewport coordinate space, while the last two provide its dimensions.

It's crucial to pay attention to the viewBox values, as they will remain constant even as attributes on the <rect> change. A pink dot has been included as a reference point when adjusting the viewBox.

Notice how the gold box is positioned 5 units from the right and 5 units down from the upper left corner of the viewport coordinate space origin at 0,0.

Gold box centered within the viewBox.

The viewBox starts with the same origin as the viewport coordinate space.

The gold box begins 5 units from the right and is 20 units wide, requiring the third parameter of the viewBox to be at least 25 in order to display the entire box. To maintain equal spacing, we add 5 to the width for a total of 30.

svg {
  width: 50%;
  border: 1px dashed indianred;
}
<svg viewBox="0 0 30 30">
  <rect x="5" y="5" width="20" height="20" fill="gold"/>
</svg>

viewBox beginning in the middle of the gold box.

The viewBox commences at 15,15 within the viewport coordinate space.

The gold box is offset by 5 to start, with half of its width being 10,

svg {
  width: 50%;
  border: 1px dashed indianred;
}
<svg viewBox="15 15 30 30">
  <rect x="5" y="5" width="20" height="20" fill="gold"/>
  <circle cx="15" cy="15" r="1" fill="hotpink"/>
</svg>

viewBox doubled in size compared to the initial example.

The viewBox maintains the same origin as the viewport coordinate space.

This new viewBox displays a 60x60 section of the viewport coordinate space. Since the gold box is drawn and positioned within a smaller space than 60x60, more of the viewport's coordinates become visible, resulting in a zoom out effect.

svg {
  width: 50%;
  border: 1px dashed indianred;
}
<svg viewBox="0 0 60 60">
  <rect x="5" y="5" width="20" height="20" fill="gold"/>
  <circle cx="15" cy="15" r="1" fill="hotpink"/>
</svg>

viewBox halved in size compared to the initial example.

The viewBox retains the same origin as the viewport coordinate space.

This adjusted viewBox showcases a 15x15 portion of the viewport coordinate space, making only a segment of the gold box visible due to its positioning outside of the viewBox. This creates a zoom-in effect.

svg {
  width: 50%;
  border: 1px dashed indianred;
}
<svg viewBox="0 0 15 15">
  <rect x="5" y="5" width="20" height="20" fill="gold"/>
  <circle cx="15" cy="15" r="1" fill="hotpink"/>
</svg>

**Additional details may be added later.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Display the value of a shortened string

My Goal I aim to develop a method for determining the amount of a string visible before it gets cut off. Motivation In my project, there is a collection of items that can be chosen. A panel presents a concatenated string of the selected item names separa ...

Display a div when hovering over an image using jQuery

I've spent a good 30 minutes searching on Stack Overflow for a solution, but I haven't been able to find it yet. It's possible that I'm not sure what exactly to look for. Essentially, I have a div that contains an image and some text. ...

Mastering the art of changing text color based on element class name in CSS3

Is it possible to dynamically set the text color of a list item based on the class name of its nested span element? For example, if the span has a class of "green", the text color of the parent li should also be green. How can this be achieved? Demo:https ...

How can I eliminate the empty spaces around a bar chart in Kendo UI?

Struggling to eliminate the extra space surrounding the Kendo UI chart below. Could this be due to a gap or spacing issue? The goal is to create a single-line bar chart with only grey appearing on the right side. Access JSFiddle Codes Here $(doc ...

"Stuck: CSS Div Transition Effect Refuses to Cooper

I am looking to incorporate a transition on my div when it is clicked. I've tried using jQuery with this example: http://jsfiddle.net/nKtC6/698/, but it seems to not be working as expected. So, I want to explore another example using CSS: http://jsfid ...

Rows intersecting and stacking above one another

I designed a layout with some text and icons displayed in rows. While it appears properly on iOS, the rows overlap on Android. const criteriaList = [ { id: 0, title: 'Noor', checked: false }, { id: 1, title: 'Friends & Grades', ...

Problem with transitions not working properly in Vue.js.The issue

Experiencing an issue with the Vue.js transition feature. Check out this link for reference. When the transition enters, it works smoothly, but when transitioning out, it's not functioning properly. File: genetic.vue <transition name="slide-f ...

Place the button inside the form following another block element

Here is the HTML code I am working with: <div class="actions"> <input id="submit-car" name="commit" type="submit" value="Добавить объявление"> </div> and here is a fiddle example: http://jsfiddle.net/348U4/ In ...

Which HTML element does each script correspond to?

Are there any methods to identify the script used in certain HTML elements? For instance, if I wish to determine the script responsible for creating a drop-down menu, I can locate the HTML and CSS for the menu but not the JavaScript (or other scripts). I ...

In order to design a v-btn-toggle with vertically aligned buttons, rather than horizontally

I'm currently in the process of developing a quiz using VueJS and Vuetify. My challenge lies in organizing the answer options vertically for the user to select. I attempted to utilize the v-btn-toggle component, but encountered an issue where the butt ...

Tips on resolving issues with form input that is not accepting input on a Mobile device

As a newbie in HTML and CSS, I attempted to design a form with various fields. While the fields work perfectly on larger screens, they do not allow input on smaller screens (mobile devices). I used the Firefox inspect tool to troubleshoot the issue, but c ...

Whenever I adjust the layout of the navigation bar, the edges end up getting clipped

I'm having trouble with the border shape of my navbar. When I try to make it a rounded pill shape, the edges get cut off instead of being properly displayed. https://i.stack.imgur.com/sUN2Y.png Below is the HTML template: <template> <div cl ...

What is the best method for centering text input within an Angular Material toolbar?

Can anyone help me with aligning input elements with buttons on an Angular Material toolbar? Check out the code pen: http://codepen.io/curtwagner1984/pen/amgdXj Here is the HTML code: <md-toolbar class="md-hue-1" layout-align="start center" style="mi ...

Implementing dynamic class changes with *ngIf within a child component

Apologies if this question has been addressed before, I found two similar answers here: Question related | Close Solution An Angular Material Sidenav component contains three components. The parent component (highlighted in red) includes tab-like but ...

Ways to display a vertical scrollbar within a select box

I'm currently working with an Angular select box and I'm looking to display a scroll bar if there are more than 5 data entries. <select class="form-control" data-ng-model='projectListData.appVersion' ng-selected ng-options="v.versio ...

What is the best way to design versatile div containers that combine the float property with fluid dimensions?

I am attempting to achieve a specific layout where the width of the content_container extends up to the right side of the screen and dynamically adjusts based on whether the expandable pane is collapsed or expanded. Applying width: 100% to .content_contain ...

Adjusting the margins of jQuery mobile buttons

I seem to be stuck on a simple error that is causing me to spin my wheels. Take a look at the following jqm (version 1.3) view (in haml) #main-header{'data-role' => 'header'} #main-content{'data-role' => 'content ...

How to use CSS to align text at the bottom of Angular Material icons within spans?

Looking for assistance with this code snippet. I am trying to align the text within the spans to the bottom of the stars. <ng-container *ngIf="starCount"> <span>Not Relevant</span> <button mat-icon-button ...

Trouble with CSS: Auto Margin not aligning content centrally

Despite my efforts to simplify the code, I am still struggling to center it. It seems that my lack of experience with CSS is hindering me from grasping a simple solution. If anyone has any valuable resources for learning CSS, I would greatly appreciate it ...

Issue with multi-level bootstrap navbar: Unable to hover on child elements

Currently, I am working on implementing a multi-level navbar in my project using Bootstrap Navbar along with additional CSS and Jquery. If you want to review the codes, they can be found at: CodePen $(function() { // ------------------------------- ...