1

I'm trying to rotate a graph made in SVG when the viewport is smaller than 600px. I used a media querie and it work great but the svg is overflowing from it's container and whatever I do, I can't fix it.

Is it possible to fix it without javascript ?

I tried to use the preserveAspectRatio attribute and the viewbox attribute but it doesnt work.

Here's the code : https://codepen.io/telumire-the-sasster/pen/vYBxLRg

HTML :

<div class="container">

  <svg viewBox="0 0 700 100" preserveAspectRatio="none" class="graphic" style="">
              <polyline fill="red" stroke="none"
                    points="
                            0,0
                            0,15
                            100,14
                            200,18
                            300,21
                            400,23
                            500,22
                            600,17
                            700,17
                            700,0
                            0,0
                            "/>
              </svg>
</div>

CSS :

    .container {
  background-color: green;
}
.graphic {
  transform: scaleY(-1);
}

@media (max-width: 599px) {
  /* smartphone */
  .graphic {
    transform: rotate(90deg);
    height: 100%;
    display: block;
  }
}

I expect the svg to not overflow from the green container (it must fit it's height).

Télumire
  • 13
  • 4

2 Answers2

0

The height of your svg doesnt not exceed the height of your container. Problem is you turn your svg 90 degrees so that visually it's width becomes it's height, but that's only visually, cos it's still counted as width.

EDIT: Added a jQuery solution. With this setup if viewport is smaller than 600 your svg will be rotated as before but JavaScript will replace height value with width value and width value with height value. Here is the code:

$(window).resize(function() {
  if ($(window).width() <= 600) {
    var h = $('#svg').height();
    var w = $('#svg').width();
    $('#svg').attr('width', h);
    $('#svg').attr('height', w);
  }
});
.container {
  background-color: green;
}

.graphic {
  transform: scaleY(-1);
}

@media (max-width: 599px) {

  /* smartphone */
  .container {
    height: 200px;
  }

  .graphic {
    transform: rotate(90deg);
    height: 100%;
    display: block;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">

  <svg viewBox="0 0 700 100" preserveAspectRatio="none" class="graphic" style="" id="svg">
    <polyline fill="red" stroke="none" points="
                            0,0
                            0,15
                            100,14
                            200,18
                            300,21
                            400,23
                            500,22
                            600,17
                            700,17
                            700,0
                            0,0
                            " />
  </svg>
</div>

Other choice would be placing 2 svgs (one vertically and one horizontally aligned) and displaying only one of them at a time.

rybchenko95
  • 118
  • 1
  • 6
  • ok, I see ! Do you know how I can make the width fit the container then ? I tried with width:100% but it doesnt seem to works, and I cant give a fixed width to the container :/ – Télumire Aug 25 '19 at 01:02
  • Look at it as this - first your element width and height are calculated and only then you are turning it 90 degrees. It's not very clear what is your exact goal here. To make it take 100% of it's parent height while being rotated meanwhile preserving aspect ratio? – rybchenko95 Aug 25 '19 at 01:16
  • 1
    Yes, I've read several articles talking about this, apparently there are workaround (example here https://stackoverflow.com/questions/21248111/overflow-behavior-after-using-css3-transform) but it doesnt work with my code ... Here's what I want to do : https://imgur.com/Du6rp4n When the viewport is under a certain width, the graphic must be rotated at 90° and take 100% of the height of it's container. Sorry if I'm not clear .. – Télumire Aug 25 '19 at 01:29
  • Edited my answer. Tell me if it works as you intended. – rybchenko95 Aug 25 '19 at 01:48
  • I've seen your edit and that's exactly what I wanted ! You must be right, CSS doesnt seem capable of doing that .. just one thing : when i expand the navigator window back to it's initial width, the svg doesnt return to it's initial state. I think I can work around it tough, thanks for your help ! 2 svg is also a good idea, I will try it – Télumire Aug 25 '19 at 01:51
  • It is not designed for dynamic window width, could be done but would be more complicated and i think it is unnecessary considering what your goal is here. But if your window width is static it should work just fine both on desktop and mobile. – rybchenko95 Aug 25 '19 at 02:02
0

For anyone interested, I've finally settled with using 2 inline svg :

HTML :

<div class="container">
      <svg
        viewBox="0 0 700 100"
        preserveAspectRatio="none"
        class="graphic landscape"
      >
       <!-- <g transform="translate(0,100)"></g><g transform="scale(1,-1)"></g> -->

       <polyline
          fill="lightgrey"
          stroke="none"
          points="
                          0,0
                          0,60
                          100,56
                          200,72
                          300,84
                          400,92
                          500,88
                          600,68
                          700,68
                          700,0

                          "
        />
      </svg>

      <svg
        viewBox="0 0 100 700"
        preserveAspectRatio="none"
        class="graphic portrait"
      >
        <!-- <g transform=" translate(0,100) "></g><g transform="scale(1,-1) "></g> -->

        <polyline
          fill="lightgrey "
          stroke="none "
          points=" 
          0,0
          60,0 
          56,100 
          72,200 
          84,300 
          92,400 
          88,500 
          68,600 
          68,700 
          0,700 

          "
        />
      </svg>
    </div>

CSS :

 .container {
        background-color: green;
        height: 50vh;
      }
      .graphic {
        transform: scaleY(-1);

        overflow-x: hidden;
        overflow-y: hidden;
      }

      .landscape {
        display: block;
        width: 100%;
        /* max-height: 100%; */
        height: 100%;
      }
      .portrait {
        display: none;
        height: 100%;
        /* max-width: 100%; */
        width: 100%;
      }
      @media (max-width: 599px) {
        /* smartphone */
        .portrait {
          display: block;
        }
        .landscape {
          display: none;
        }
      }

Next step is using js to automate the coordinate of the second graph I guess

EDIT: You should actually use display: none; and display: block; here, since visibility: hidden; and visibility: visible; doesnt show the tag too but allocate space for it and we want to avoid that.

Télumire
  • 13
  • 4