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,
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
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>
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"
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>
Flexbox browser support: caniuse flexbox
Learn about Flexbox: CSS Tricks Guide to Flexbox
Learn by playing: Flexbox Froggy
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;
Related
I am trying to align an SVG to the right of a div as shown below.
No matter what style I add to the SVG it does not seem to move.
I have tried adding display: flex with justify-content:end and that hasn't worked. I also tried float: right and that didn't work. Lastly, I tried margin-left: 50% and that doesn't even seem to move it.
I'm so confused.
Here is my SVG
`
<svg width="14" height="15" xmlns="http://www.w3.org/2000/svg">
<path id="cross-icon" onclick="closeModal();"
d="m11.596.782 2.122 2.122L9.12 7.499l4.597 4.597-2.122 2.122L7 9.62l-4.595 4.597-2.122-2.122L4.878 7.5.282 2.904 2.404.782l4.595 4.596L11.596.782Z"
fill="#69707D" fill-rule="evenodd"/>
</svg>
`
Here is my css
`
#cross-icon {
fill: black;
margin: 0 auto !important;
top: -8%;
position: absolute;
}
`
You're applying the class to the path attribute. I wouldn't do it this way. Wrap the entire SVG inside of another div and apply the styling as follows.
<button class="close">
<svg width="14" height="15" xmlns="http://www.w3.org/2000/svg">
<path
d="m11.596.782 2.122 2.122L9.12 7.499l4.597 4.597-2.122 2.122L7 9.62l-4.595 4.597-2.122-2.122L4.878 7.5.282 2.904 2.404.782l4.595 4.596L11.596.782Z"
fill="#69707D" fill-rule="evenodd"/>
</svg>
</button>
.close{
position: absolute;
z-index: 999;
right: 3rem;
top: 3rem;
cursor: pointer;
}
https://jsfiddle.net/cp2z9omn/
don't apply style to the <path> element
instead affect the whole <svg> (use an id if you want-- my example does not)
float: right & display: inline are easy, simple to understand, and highly effective. You may not even need to position: absolute. My example does not.
svg
{
fill: black;
top: -8%;
display: inline;
float: right;
cursor: pointer
}
<div style="width: 80%; height: 60%; margin: auto">`SOME OTHER CONTENT (YOUR BOX)`</div>
<svg width="14" height="15" xmlns="http://www.w3.org/2000/svg">
<path onclick="closeModal();"
d="m11.596.782 2.122 2.122L9.12 7.499l4.597 4.597-2.122 2.122L7 9.62l-4.595 4.597-2.122-2.122L4.878 7.5.282 2.904 2.404.782l4.595 4.596L11.596.782Z"
fill="#69707D" fill-rule="evenodd"/>
</svg>
This question already has answers here:
Image inside div has extra space below the image
(10 answers)
Closed 9 months ago.
Quick question and a very simple HTML CSS question but I'm not getting it.
Here is my image rendering inside of a tag.
I don't really understand why there's a gap kind of padding-bottom in the aside which is not allowing my image to sit on the bottom => just like it would be bottom:0 if we were talking about position: absolute (which is not the case tho).
Here's the code:
<aside
class="aside"
>
<h1>This is the aside</h1>
<h2
>
Join this great community!
</h2>
<div class="link-container">
<a
class="link"
href="https://app.redpadel.com"
> Link </a
>
</div>
<div class="icon-container">
<svg
width="160"
height="161"
viewBox="0 0 160 161"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12.9859 35.5114C12.9859 35.5114 14.7383 71.4143 37.308 84.3381C53.2318 93.4563 73.9771 87.9876 73.4958 75.7778C73.2413 69.3196 66.3035 68.1061 62.0894 70.5929C54.473 75.0874 59.0025 94.4066 67.3688 102.896C96.385 132.339 151.835 110.545 151.835 110.545"
stroke="white"
stroke-width="2"
stroke-linecap="round"
/>
<path
d="M147.668 119.084L152.597 110.624L143.688 104.809"
stroke="white"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</div>
<div
class="img-container"
>
<img
class="image"
:src="require('../assets/img/capsule_member.jpg')"
alt="Padel team"
/>
</div>
</aside>
<style scoped>
aside {
background: rgb(19, 20, 21);
width: 90%;
margin: 0;
padding: 0;
}
.link {
color: #fff;
text-decoration: none;
}
.image {
width: 100%;
height: 100%;
margin: 0;
}
.img-container {
margin: 0;
padding: 0;
}
</style>
The body is set to margin & padding: 0
Use display: block on the image, otherwise it's treated as an inline element, keeping space for descenders below the baseline.
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).
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.
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.
I have a requirement to display 2 circles with different widths and heights but circles should start from same origin ( same center ), it means even though I change the sizes of both the circles they should look same with different sizes.
I have seen some bunch of examples over internet,problem with them is when I change the width and heights center point of both the circles are not the same anymore.
Also when I do hover they have to increase the size with smooth transition.
I am guessing that I need two circles to draw something like this, if we can draw with using only one circle please let me know.
Outer circle details:
inner circle
width: 97.33px;
height: 97.33px;
color: #DEBF43;
opacity: 74%;
shadow: #D7E0F1, 100%;
blur: 30px;
x - 0px //no idea but is mentioned in requirement
y 10px //no idea but is mentioned in requirement
outer circle details:
width: 79.49
height: 79.49
shadow: #000000,15%;
blur: 6px;
opacity: 100%;
X - 0px //no idea but is mentioned in requirement
y - 1px //no idea but is mentioned in requirement
Thanks,
Rohan
I would use a SVG with circles. It is quite easy and well readable.
Get two circles aligned with different radius and manipulate them via Javascript. Just overwrite the r-property.
Here a quick example with Vue:
new Vue({
el: '#app',
data: {
r1: 120,
r2: 90,
}
});
/* circles */
.circle--1 {
fill: yellow;
}
.circle--2 {
fill: orange;
}
.transparent {
opacity: 0.4;
}
/* demo stuff */
.container {
display: flex;
flex-flow: row wrap;
justify-content: center;
align-content: flex-start;
background: #ccc;
height: 100vh;
}
.svg, aside {
background-color: #fff;
box-shadow: 0 0 4rem #00000033;
margin: 1rem;
}
aside {
width: 300px;
height: 300px;
display: flex;
flex-flow: column;
justify-content: space-evenly;
align-items: center;
}
label {
display: block;
font-weight: 700;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<main id="app" class="container">
<!-- svg with two circles -->
<svg class="svg" width="300" height="300">
<circle class="circle circle--1" cx="50%" cy="50%" r="120" stroke="black" stroke-width="2"/>
<circle class="circle circle--2" cx="50%" cy="50%" r="90"/>
</svg>
<!-- demo svg with editable radii -->
<svg class="svg" width="300" height="300">
<circle id="circle-1" class="circle circle--1 transparent" cx="50%" cy="50%" :r="r1" stroke="black" stroke-width="2"/>
<circle id="circle-2" class="circle circle--2 transparent" cx="50%" cy="50%" :r="r2"/>
</svg>
<!-- demo controls -->
<aside>
<section>
<label for="radius1">Radius 1 ({{r1}}px)</label>
<input type="range" id="radius1" min="0" max="140" v-model="r1">
</section>
<section>
<label for="radius2">Radius 2 ({{r2}}px)</label>
<input type="range" id="radius2" min="0" max="140" v-model="r2">
</section>
</aside>
</main>
Here is a simple idea where you can rely on multiple background. The trick is to make the gradient to cover only the content box and control the space using padding:
.box {
width:100px;
height:100px;
border-radius:50%;
border:5px solid;
padding:20px;
background:
linear-gradient(orange,orange) content-box,
yellow;
}
<div class="box">
</div>
Or like this with a radial-gradient
.box {
width:100px;
height:100px;
border-radius:50%;
border:5px solid;
padding:20px;
background:
radial-gradient(farthest-side,orange 60%,yellow 61%);
}
<div class="box">
</div>
TLDR: i want to achive this as scalable solution:
Longer explanation:
Target is to have a rotated div with a gradient as background. But the problem is that the rotation cant be defined as deg because it varies depending on the browser-width. So the element should be 100% width of the browser with a fixed height on the left and a fixed lower height on the right side.
Basically this can be done easily with an image-background which stretches only horizontally. Only problem is that there should be also a pattern overlay which should be clipped on the same area and this should repeat and not stretch (as you can see these pattern consists of equal boxes)
So my idea was: Is it possible to rotate an element for specific target pixels?
Current Example:
.triangleClipper {
height: 100px;
overflow: hidden;
}
.designElement {
background: linear-gradient(to right, #03cc65, #fbfe02);
height: 100px;
width: 200%;
transform-origin: top left;
transform: rotate(-2deg);
margin-top: -60px;
}
https://jsfiddle.net/0egg320q/
You see the problem on the right edge when resizing the browser. So on width screens you see the end of the triangle and small screens it is too high. Target is to remain same heights on left and right edges on every browser size.
Any other ideas are welcome.
You may use clip-path with percentage. Like this you will always have your fixed heights, then you may simply rotate the linear gradient as you need :
body {
background:#ccc;
}
.triangleClipper {
height: 100px;
overflow: hidden;
}
.designElement {
background: linear-gradient(10deg, #03cc65, #fbfe02);
height: 100px;
width: 100%;
-webkit-clip-path: polygon(120% 0, 0 0, 0 100%);
clip-path: polygon(120% 0, 0 0, 0 100%);
}
<div class="triangleClipper">
<div class="designElement"></div>
</div>
You only need to pay attention as this property it not supported by all browser.
Another solution using pseudo element, but in this case you will have the bottom part colored and not transparent :
body {
background:#ccc;
}
.triangleClipper {
height: 100px;
overflow: hidden;
}
.designElement {
background: linear-gradient(10deg, #03cc65, #fbfe02);
height: 100%;
width: 100%;
position:relative;
overflow:hidden;
}
.designElement:after {
content: "";
position: absolute;
border-right: 120vw solid #fff;
border-bottom: 100px solid #fff;
border-top: 100px solid transparent;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="triangleClipper">
<div class="designElement"></div>
</div>
UPDATE
Another good solution using skew transformation and some % properties. This solution will not make the heights fixed but it will make the ratio of the two height fixed. It can be interesting one too.
body {
background: #ccc;
}
.triangleClipper {
width: 100%;
overflow: hidden;
padding-top: 30%;
}
.designElement {
background: linear-gradient(to right, #03cc65, #fbfe02);
padding-top: 100%;
margin-top: -120%;
width: 100%;
transform: skewY(-7deg);
}
<div class="triangleClipper">
<div class="designElement"></div>
</div>
After searching for a cross-browser way for clip-path (especially IE) i found out that using an SVG is the best solution for that.
Sadly an SVG dont support percentage values for polygons so i could only fix this via adding JavaScript and correcting the values live depending on browser size.
(In basic the SVG works for scaling the object, JS is only there for correcting the pattern-image-output.)
$(function() {
//svg der fensterbreite anpassen
var fullWidth = $('.styleElementTop').width();
console.log(fullWidth);
$('.styleElementTop svg')[0].setAttribute('viewBox', '0 0 ' + fullWidth + ' 100');
$('.styleElementTop #gradientFill')[0].setAttribute('points', '0,0 0,100 ' + fullWidth + ',10 ' + fullWidth + ',0');
$('.styleElementTop #patternFill')[0].setAttribute('points', '0,0 0,100 ' + fullWidth + ',10 ' + fullWidth + ',0');
});
body {
padding: 0px;
margin: 0px;
}
.styleElementTop {
height: 100px;
width: 100%;
}
#gradientFill {
fill: url(#mainGradient);
}
#patternFill {
fill: url(#mainPattern);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="styleElementTop">
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 700 100" preserveAspectRatio="none">
<defs>
<linearGradient id="mainGradient">
<stop stop-color="#03cc65" offset="0%" />
<stop stop-color="#fbfe02" offset="100%" />
</linearGradient>
<pattern id="mainPattern" x="0" y="0" width="10" height="10" patternUnits="userSpaceOnUse">
<image width="10" height="10" xlink:href="https://live.tlprod.de/temp/whitepattern.png" />
</pattern>
</defs>
<polygon id="gradientFill" points="0,0 0,100 700,10 700,0"></polygon>
<polygon id="patternFill" points="0,0 0,100 700,10 700,0"></polygon>
</svg>
</div>