Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stretch a svg-element to full height of a flex container

I have a container with display: flex. At both corners a svg-element should stretch to the full height of the container. The Height of the container depends on how much text is in the element.

In FF and Chrome it works perfect, but IE makes the svg always 150px height. I can't give the svg a fixed size, because it should stretch with the element if the text becomes multiline and the element grows.

I have done a codepen here

.flag-header {
  display: flex;
  max-width: 80%;
  position: relative;
}

.flag-header__headline {
  background-color: #bf0b1c;
  padding: 10px 0;
  color: white;
  font: 900 24px/120% Verdana;
  text-transform: uppercase;
}

.flag-header__corner {
  width: 30px;
}

.flag-header__corner-shape {
  height: 100%;
  width: 30px;
  fill: #bf0b1c;
}
<div class="flag-header">
  <div class="flag-header__corner">
    <svg class="flag-header__corner-shape" id="Layer_1" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 22.11 30" preserveAspectRatio="none">
        <polygon class="cls-1" points="22.11 30 0 30 10 15 0 0 22.11 0 22.11 30"/>
            </svg>
  </div>
  <p class="flag-header__headline">sdfgsdgfsdgf sfasd fasdf asdfasdf</p>
  <div class="flag-header__corner">
    <svg class="flag-header__corner-shape" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.11 30" preserveAspectRatio="none">
            <polygon class="cls-1" points="0 30 22.11 30 12.11 15 22.11 0 0 0 0 30"/>
            </svg>
  </div>
</div>
like image 377
Gregor Voinov Avatar asked Sep 29 '16 16:09

Gregor Voinov


People also ask

How do I make my Flexbox 100% height?

Getting the child of a flex-item to fill height 100% Set position: absolute; on the child. You can then set width/height as required (100% in my sample).

Can you stretch an SVG?

Option 1: Use percentages. One option to stretch to fit is to use percentage values for all size and position attributes in the SVG. Things to note about percentages and SVG: If you're using percentages to stretch and squish, don't include a viewBox (although you can specify default height and width).

How do I scale SVG viewBox?

We use viewBox to make the SVG image scalable. viewBox = “0 0 100 100”: defines a coordinate system having x=0, y=0, width=100 units and height=100 units. Thus, the SVG containing a rectangle having width=50px and height=50px will fill up the height and width of the SVG image, and all the dimensions get scaled equally.

Does Flex work on SVG?

Applying Flexbox to SVG The top and left layout properties are applied as a transform, whereas the height and width are written to layout-height and layout-width attributes respectively. The reason for this is that SVG group elements ( g ) have an origin but do not have a width or height.


1 Answers

Not an answer. At best a hack. Just more observations into this unexpected behavior. Perhaps it's a bug.

Removing the svg wrapper and removing height: 100% from the svg has the same effect. (Closer to the layout I'm trying to debug. Good to know the wrapper OP started with makes no difference and I can avoid an unnecessary element.)

.flag-header {
  display: flex;
  max-width: 80%;
  position: relative;
}

.flag-header__headline {
  background-color: #bf0b1c;
  padding: 10px 0;
  color: white;
  font: 900 24px/120% Verdana;
  text-transform: uppercase;
}

.flag-header__corner-shape {
  width: 30px;
  fill: #bf0b1c;
}
<div class="flag-header">
  <svg class="flag-header__corner-shape" id="Layer_1" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 22.11 30" preserveAspectRatio="none">
        <polygon class="cls-1" points="22.11 30 0 30 10 15 0 0 22.11 0 22.11 30"/>
            </svg>
  <p class="flag-header__headline">sdfgsdgfsdgf sfasd fasdf asdfasdf</p>
  <svg class="flag-header__corner-shape" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.11 30" preserveAspectRatio="none">
            <polygon class="cls-1" points="0 30 22.11 30 12.11 15 22.11 0 0 0 0 30"/>
            </svg>
</div>

A hack by inverting the variable height element's padding with negative margins on the variable element and the svg elements.

.flag-header {
  display: flex;
  max-width: 80%;
  position: relative;
  border: 1px solid black;
}

.flag-header__headline {
  background-color: #bf0b1c;
  padding: 10px 0;
  margin: -10px 0;
  color: white;
  font: 900 24px/120% Verdana;
  text-transform: uppercase;
}

.flag-header__corner-shape {
  width: 30px;
  fill: #bf0b1c;
  margin: -10px 0;
}
<div class="flag-header">
  <svg class="flag-header__corner-shape" id="Layer_1" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 22.11 30" preserveAspectRatio="none">
        <polygon class="cls-1" points="22.11 30 0 30 10 15 0 0 22.11 0 22.11 30"/>
            </svg>
  <p class="flag-header__headline">sdfgsdgfsdgf sfasd fasdf asdfasdf</p>
  <svg class="flag-header__corner-shape" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.11 30" preserveAspectRatio="none">
            <polygon class="cls-1" points="0 30 22.11 30 12.11 15 22.11 0 0 0 0 30"/>
            </svg>
</div>

The hack falls apart without the arbitrary padding and margins. This implies that neither of those properties by themselves cause the issue, nor they can fix the issue by themselves, but they can fix it by working together to negate each other...

.flag-header {
  display: flex;
  max-width: 80%;
  position: relative;
  border: 1px solid black;
}

.flag-header__headline {
  background-color: #bf0b1c;
  color: white;
  font: 900 24px/120% Verdana;
  text-transform: uppercase;
}

.flag-header__corner-shape {
  width: 30px;
  fill: #bf0b1c;
}
<div class="flag-header">
  <svg class="flag-header__corner-shape" id="Layer_1" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 22.11 30" preserveAspectRatio="none">
        <polygon class="cls-1" points="22.11 30 0 30 10 15 0 0 22.11 0 22.11 30"/>
            </svg>
  <p class="flag-header__headline">sdfgsdgfsdgf sfasd fasdf asdfasdf</p>
  <svg class="flag-header__corner-shape" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.11 30" preserveAspectRatio="none">
            <polygon class="cls-1" points="0 30 22.11 30 12.11 15 22.11 0 0 0 0 30"/>
            </svg>
</div>

Converting to grid doesn't fix anything. Even the hack stops working. Mess with height and width in the svg element and there are some very odd results.

.flag-header {
  display: grid;
  max-width: 80%;
  position: relative;
  grid-template-columns: 30px auto 30px;
  border: 1px solid black;
}

.flag-header__headline {
  background-color: #bf0b1c;
  padding: 10px 0;
  color: white;
  font: 900 24px/120% Verdana;
  text-transform: uppercase;
}

.flag-header__corner-shape {
  fill: #bf0b1c;
}
<div class="flag-header">
  <svg class="flag-header__corner-shape" id="Layer_1" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 22.11 30" preserveAspectRatio="none">
        <polygon class="cls-1" points="22.11 30 0 30 10 15 0 0 22.11 0 22.11 30"/>
            </svg>
  <p class="flag-header__headline">sdfgsdgfsdgf sfasd fasdf asdfasdf</p>
  <svg class="flag-header__corner-shape" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.11 30" preserveAspectRatio="none">
            <polygon class="cls-1" points="0 30 22.11 30 12.11 15 22.11 0 0 0 0 30"/>
            </svg>
</div>

Converting to table doesn't fix anything. The height value in the svg element is irrelevant. Removing the height has an effect, though not what we want.

.flag-header {
  display: flex;
  max-width: 80%;
  position: relative;
  border-collapse: collapse;
  border-spacing: 0;
}

td {
  padding: 0;
}

.flag-header__headline {
  background-color: #bf0b1c;
  padding: 10px 0;
  color: white;
  font: 900 24px/120% Verdana;
  text-transform: uppercase;
}

.flag-header__corner-shape {
  width: 30px;
  fill: #bf0b1c;
  height: 100%;
}
<table class="flag-header">
  <tbody>
    <tr>
      <td>
        <svg class="flag-header__corner-shape" id="Layer_1" xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 22.11 30" preserveAspectRatio="none">
        <polygon class="cls-1" points="22.11 30 0 30 10 15 0 0 22.11 0 22.11 30"/>
            </svg>
      </td>
      <td>
        <p class="flag-header__headline">sdfgsdgfsdgf sfasd fasdf asdfasdf</p>
      </td>
      <td>
        <svg class="flag-header__corner-shape" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.11 30" preserveAspectRatio="none">
            <polygon class="cls-1" points="0 30 22.11 30 12.11 15 22.11 0 0 0 0 30"/>
            </td>
            </svg>
    </tr>
  </tbody>
</table>

Converting to pseudo-elements doesn't fix it. Lost CSS styling on the base64 encoded version of the raw SVG. That could be worked around with refs to a .svg file instead or inline CSS styles.

Thanks to: https://stackoverflow.com/a/32046349/2578125

.flag-header {
  display: flex;
  max-width: 80%;
  position: relative;
}

.flag-header__headline {
  background-color: #bf0b1c;
  padding: 10px 0;
  color: white;
  font: 900 24px/120% Verdana;
  text-transform: uppercase;
}

.flag-header::before,
.flag-header::after {
  width: 30px;
  fill: #bf0b1c;
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22.11 30' preserveAspectRatio='none'%3E%3Cpolygon points='22.11 30 0 30 10 15 0 0 22.11 0 22.11 30'/%3E%3C/svg%3E");
}

.flag-header::after {
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22.11 30' preserveAspectRatio='none'%3E%3Cpolygon points='0 30 22.11 30 12.11 15 22.11 0 0 0 0 30'/%3E%3C/svg%3E");
}
<div class="flag-header">
  <p class="flag-header__headline">sdfgsdgfsdgf sfasd fasdf asdfasdf</p>
</div>

Trying to merge the approach by @Alexei Zababurin with the OP's objectives. What works with such genius elegance for Alexei turns into a misshapen monstrosity here... The overrides are the only way to even show some of the content.

Ok, time to put this white whale to bed for a while before I completely lose my mind. May smarter and braver men prevail. Godspeed!

.flag-header {
  max-width: 80%;
  background-color: #bf0b1c;
  padding: 10px 0;
  color: white;
  font: 900 24px/120% Verdana;
  text-transform: uppercase;
  position: relative;
  z-index: 1;
  overflow: hidden;
  margin: 0 30px;
  overflow: initial;
}

.flag-header::before,
.flag-header::after {
  width: 30px;
  fill: #bf0b1c;
  display: inline-block;
  margin: 0 0 0 -100%;
  margin: 0 0 0 -30px;
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22.11 30' preserveAspectRatio='none'%3E%3Cpolygon points='22.11 30 0 30 10 15 0 0 22.11 0 22.11 30'/%3E%3C/svg%3E");
}

.flag-header::after {
  margin: 0 -100% 0 0;
  margin: 0 -30px 0 0;
  content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22.11 30' preserveAspectRatio='none'%3E%3Cpolygon points='0 30 22.11 30 12.11 15 22.11 0 0 0 0 30'/%3E%3C/svg%3E");
}
<div class="flag-header">sdfgsdgfsdgf sfasd fasdf asdfasdf
</div>
like image 99
OXiGEN Avatar answered Oct 11 '22 09:10

OXiGEN