垂直居中SVG标签

18

我正在尝试找到一种方法来垂直居中我的SVG标签。

基本上,这是一个简化的SVG代码,我正在尝试居中:

<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> 

水平方向上把它放在中间对我来说没有问题,但我也想让它垂直居中。

我可以添加包装器,但我想知道一种通用的方法来做到这一点,不依赖于SVG大小或窗口大小。

我已经尝试了多种方法,但没有任何效果。

谢谢,


2
可能是重复的问题:最佳方法在页面上垂直和水平居中一个<div>? - 这与SVG无关。 - Potatoswatter
我已经尝试过这个,但它会裁剪我的SVG的一部分... - Cuva
1
请注意,默认情况下,SVG元素的display属性为inline,因此如果您希望它的行为更像一个<div>元素,您还需要指定svg { display: block } - Erik Dahlström
5个回答

25

因为现在的浏览器有更好的解决方案,所以我更新了这个答案。

正如一位智者所说,第一年你学习html和css,再过几年你学习高级javascript,五年后你终于学会了如何垂直居中div。

要在css中水平或垂直对齐任何内容,您可以使用两种主要方法:

绝对定位

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

和CSS:

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

唯一的问题是该元素不会生成高度。

弹性盒子

弹性盒子现在有相当好的支持,为什么不使用呢。https://caniuse.com/#feat=flexbox

使用弹性盒子,您的项目不需要绝对定位,因此它将生成高度。 代码:

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

以及 CSS:

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

旧答案:

你有高度和宽度,所以可以使用 margin : auto auto;

或者将其放在一个带有 div 的标签中。

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

如果您要对其进行一些操作(例如JavaScript动画或其他操作),第二个选项会更好。

我没有检查过,但也许您也可以将第二个选项用于SVG(不需要外部div)。


谢谢您的回答,我尝试将margin: auto auto; 添加到我的SVG标签中,但它没有改变任何东西...作为第二个选项,我更愿意使用一种“通用”的方法来实现它(我希望它对于所有具有!=维度的SVG标签都是相同的包装器...) - Cuva
请记住,在使用margin:auto时,SVG的外部容器(div、body等)需要指定宽度和高度(如果您想像margin:0 auto;一样使用它,则只需要指定一个)。由于这个原因,您可能会遇到第二个位置(垂直)的问题。 - Maciej Paprocki
margin: auto auto;margin: auto; 有什么不同? - user663031
@MaciejPaprocki 谢谢您的评论。我尝试在外部容器上添加height="100%" width="100%",但没有任何变化。还有其他方法吗?顺便说一下,我已经找到了另一种解决方案,如我的答案所述,它可以很好地工作,但如果不使用JS的话,那就更好了 :) - Cuva
是的,但对于 margin: auto,您需要指定高度和宽度(例如200px),而不是使用百分比。而且,margin:auto automargin:auto 相同,但我通常使用前者的形式; - Maciej Paprocki
在思考了几秒钟之后,我不确定外部容器是否需要在像素中指定宽度和高度(如果它与 body 一起使用)。 - Maciej Paprocki

3

很简单!

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
我猜只需要将display:table-cell和vertical-align:middle设置为svg的容器,所以只需要一个div就可以了(?) - Fanky

1
你可以尝试使用flexbox
简单的HTML:
<div class="outside">
    <svg />
</div>

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

带有您的示例的HTML:

<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>

1
如果您为svg元素提供viewBox属性,并将其widthheight属性设置为100%,则大多数浏览器都应该正常(保留html标签)。

$(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>

&这里有一个对应的jsfiddle可以进行玩耍

NB: 还有一个与viewBox设置配合使用的preserveAspectRatio属性。例如:preserveAspectRatio="xMidYMid meet"


-2

我最终使用了一些JS代码来实现这个功能。

我之前使用的解决方案来源于这里:最佳方法在页面上垂直和水平居中一个<div>?

具体而言,它是:

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

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

}

但问题在于,如果SVG比窗口尺寸大,它会被裁剪。 这是我在onLoad中使用的JS代码:

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; 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接