18

I'm trying to figure out a way to center vertically my SVG Tag.

Basically, here is a simplified SVG code i'm trying to center :

<svg height="272" style="background-color:transparent;margin-left: auto; margin-right: auto;" width="130" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g style="font-size: 0.7em;" transform="scale(1 1) rotate(0) translate(0 270)">
        <g id="1" style="font-size: 0.7em;">
            <image height="32" width="32" x="49" xlink:href="../../images/JOB.GIF" y="-270"/>
        </g>
    </g>
</svg> 

I have no trouble putting it in the middle (horizontally speaking) of the page, however i'd like it to be vertically centered as well.

I can add wrappers, but i'd like to know a generic way of doing this, not depending on the SVG size nor the window size.

I have tried multiple ways, but nothing worked.

Thanks,

Cuva
  • 335
  • 1
  • 4
  • 15
  • 2
    possible duplicate of [Best way to center a
    on a page vertically and horizontally?](http://stackoverflow.com/questions/356809/best-way-to-center-a-div-on-a-page-vertically-and-horizontally) — being SVG makes no difference.
    – Potatoswatter Jan 14 '13 at 08:51
  • I have tried this, but it cuts part of my SVG... – Cuva Jan 14 '13 at 12:11
  • 1
    Note that svg is `display: inline` per default, so if you want it to behave more like a
    you also need to specify `svg { display: block }`.
    – Erik Dahlström Jan 14 '13 at 13:25

5 Answers5

25

I updated this answer as current browser have a lot better solution for that.

How wise man said, first year you learn html and css, for another few years you learn advanced javascript and after five years you finally learn how to vertically center div.

to vertically/horizontally align anything in css you can use two main ways:

Absolute

<div class="outside">
    <div class="inside">Whatever</div>
</div>

and css:

.outside{
    position:relative;
}
.inside{
    position:absolute;
    top:50%;
    bottom:50%;
    transform:translate(-50%, -50%);
}

the only issue with that is that element doesn't generate the height.

Flexbox

Flexbox has now pretty good support so why not to use it. https://caniuse.com/#feat=flexbox

Using flexbox your item doesn't need to be absolute so it will generate the height. code:

<div class="outside">
    <div>Whatever</div>
</div>

and css:

.outside{
    display: flex;
    align-items: center;
    justify-content: center;
}

Old answer:

you have height and width so u can use margin : auto auto;

or put it in div with

position:absolute ;
left:50% ;
margin-left: -(half of width of image)px;
top:50% ;
margin-top: -(half of height of image)px;

the second one will be better if u will be doing some stuff with it (javascript animation or something)

I didn't check it but maybe u can use second option for svg (without outer div) too

Maciej Paprocki
  • 1,230
  • 20
  • 29
  • Thanx for you answer, I have tried to add margin: auto auto; to my SVG tag but it doesnt change anything.... As the second option, i'd rather use a 'generic' way of doing it (I'd like it to be the same wrapper for all SVG tag which have != dimmensions...) – Cuva Jan 14 '13 at 11:36
  • remember that for using margin:auto outer container of svg (div, body etc.) need to have specified width and height(or only one if you want to use it like margin:0 auto;) because of that you probably have problem with second positioning (vertical). – Maciej Paprocki Jan 15 '13 at 08:36
  • How is `margin: auto auto;` different from `margin: auto;`? –  Jan 16 '13 at 05:53
  • @MaciejPaprocki Thanks for your comment. I've tried adding height="100%" width="100%" on the outter container but it doest change anything. Is there another way ? Btw, I've already found another solution as stated in my answer which works fine, but if there is a way without using JS it would be even better :) – Cuva Jan 16 '13 at 07:16
  • yes but for `margin: auto` you need to specify height and width (200px for example) not with %. And `margin:auto auto` is this same as `margin:auto` but i used to first form; – Maciej Paprocki Jan 17 '13 at 08:28
  • after few seconds of thinking i am not sure that outer container need to have specified width and height in px (if it work with body) – Maciej Paprocki Jan 17 '13 at 08:33
3

It's Simple!

HTML:

<div class="a">
<div class="b">
<div class="c">
<!-- Your SVG Here -->
</div>
</div>
</div> 

CSS:

<style>
.a {
display: table;
position: absolute;
height: 100%;
width: 100%;
}

.b {
display: table-cell;
vertical-align: middle;
}

.c {
margin-left: auto;
margin-right: auto; 
height: /* Your size in px, else it will expand to your screen size!*/
width:  /* Your size in px, else it will expand to your screen size!*/
}
</style>
  • 1
    I guess it's enough to set display:table-cell and vertical-align:middle to the container of the svg, so only one div is necessary (?) – Fanky Sep 08 '16 at 15:12
1

If you provide your svg element with a viewBox attribute and set it's width & height attributes to 100% then all should be well (in most browsers..)

$(document).ready(function(){
  $(".panel-left").resizable({handleSelector: ".splitter",containment: "parent"});
});
#ctr
{
 position:        absolute;
 border:          1px solid #131313;    
 top:             5%;
 left:            5%;
 bottom:          5%;
 right:           5%;    
 display:         flex;
 flex-direction:  row;    
}

#ctr svg
{
 height:    100%;
 width:     100%;
}

.panel-left 
{
  flex:         0 0 auto;
  padding:      10px;
  width:        50px;
  min-height:   50px;
  min-width:    50px;
  max-width:    80%;
  max-height:   100%;
  white-space:  nowrap;
  background:   #131313;
  color:        white;
}

.splitter 
{
  flex:         0 0 auto;
  width:        18px;  
}

.panel-right 
{
  flex:         1 1 auto;
  padding:      10px;
  min-width:    20px;
  background:   #eee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>


<div style="visibility:hidden; position:absolute; width:0">
 <svg>
   <g id="my-funky-svg-defs">
  <defs>
    <radialGradient id="gradient" cx="25%" cy="25%" r="100%" fx="40%" fy="40%">
   <stop offset=  "0%" stop-color="hsla(313,  80%, 80%, 1)"/>
   <stop offset= "40%" stop-color="hsla(313, 100%, 65%, 1)"/>
   <stop offset="110%" stop-color="hsla(313, 100%, 50%, 0.7)"/>
    </radialGradient>
  </defs>    
  <title>smarteee</title>
  <circle  class="face" cx="200" cy="200" r="195" fill="url(#gradient)" />
  <ellipse class="eye eye-left" cx="140" cy="150" rx="10" ry="40" fill="#131313"/>
  <ellipse class="eye eye-right" cx="260" cy="150" rx="10" ry="40" fill="#131313"/>
  <path class="smile" d="M120,280 Q200,330 280,280" stroke-width="10" stroke="#131313" fill="none" stroke-linecap="round"/>
   </g>
 </svg>
</div>

<div id=ctr>
 <div class="panel-left">
   <svg viewBox="0 0 400 400"><use xlink:href="#my-funky-svg-defs"></use></svg>        
 </div>

 <div class="splitter">
 </div>

 <div class="panel-right">
   <svg viewBox="0 0 400 400"><use xlink:href="#my-funky-svg-defs"></use></svg>        
 </div>
</div>

&here's a corresponding jsfiddle to play with

NB: there is also the preserveAspectRatio attribute that works in conjunction with the viewBox settings. eg: preserveAspectRatio="xMidYMid meet"

violet313
  • 1,912
  • 1
  • 15
  • 19
1

You could try using flexbox.

Simple HTML:

<div class="outside">
    <svg />
</div>

CSS:

.outside {
    display: flex;
    align-items: center; /* vertical alignment */
    justify-content: center; /* horizontal alignment */
}

HTML with your sample:

<div class="outside">
    <svg height="272" style="background-color:transparent;margin-left: auto; margin-right: auto;" width="130" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
        <g style="font-size: 0.7em;" transform="scale(1 1) rotate(0) translate(0 270)">
            <g id="1" style="font-size: 0.7em;">
                <image height="32" width="32" x="49" xlink:href="../../images/JOB.GIF" y="-270"/>
            </g>
        </g>
    </svg> 
</div>
gilalberto
  • 71
  • 3
-2

I've finally used some JS code to do so.

I was using the solution from here : Best way to center a <div> on a page vertically and horizontally?

Which is :

div {
    width: 100px;
    height: 100px;
    background-color: red;

    position: absolute;
    top:0;
    bottom: 0;
    left: 0;
    right: 0;
    margin: auto;

}

But the problem is that if the SVG is bigger than the window size, it gets cropped. Here is the JS code i've used in onLoad :

var heightDiff = window.innerHeight - svg.height.baseVal.value;
var widthDiff = window.innerWidth - svg.width.baseVal.value;
if (heightDiff > 0)                                                                                                                
    svg.style.marginTop = svg.style.marginBottom = heightDiff / 2;
if (widthDiff > 0)
    svg.style.marginLeft = svg.style.marginRight = widthDiff / 2; 
Community
  • 1
  • 1
Cuva
  • 335
  • 1
  • 4
  • 15