Wrapping svg element with CSS - html

I want to make an svg element wrapper to dynamically resize it. I use svg inside the div of the element to which the wrapper svg-wrapper class is applied. My css looks like this:
.svg-wrapper {
display: inline-block;
position: relative;
width: 100%;
padding-bottom: 100%;
vertical-align: top;
overflow: hidden;
background-color: gray;
}
svg {
display: inline-block;
position: absolute;
top: 0;
left: 0;
fill: red;
}
And html so:
<div class="svg-wrapper">
<svg preserveAspectRatio="xMinYMin meet" viewBox="0 0 300 100">
<rect width="100%" height="100%" fill="blue"/>
</svg>
</div>
Example on JSFiddle: http://jsfiddle.net/a2nj971t/
However, as you can see there is a problem that the div does not wrap the svg from below. Is it possible to fix it (Regardless of size of svg)?

Related

Position SVG at bottom of any screen

I am trying to position a SVG at bottom in any screen, but I can't do it in screens without scrollbar.
I tried some changes but nothing seems work.
Here is CSS what I use:
.custom-shape-divider-bottom-1652813835 {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
overflow: hidden;
line-height: 0;
transform: rotate(180deg);
z-index: -1;
}
.custom-shape-divider-bottom-1652813835 svg {
position: relative;
display: block;
width: calc(128% + 1.3px);
height: 600px;
}
.custom-shape-divider-bottom-1652813835 .shape-fill {
fill: var(--svg-color);
}
And there is my Html:
<div style="position: relative;">
<div class="custom-shape-divider-bottom-1652813835">
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
<path d="M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z" class="shape-fill"></path>
</svg>
</div>
</div>
When I don't have scroll this is what happens: https://i.stack.imgur.com/Kafst.png
When I have scroll the SVG fits at the bottom: https://i.stack.imgur.com/6GFDP.png
I look with element inspector and that white space is not found inside my html document.
Any sugestions please? Thanks for ur time.
EDIT:
This whats happens when delete the position relative in that div: https://i.stack.imgur.com/pRjMt.png
EDIT 2:
Added JSFiddle:
https://jsfiddle.net/bue4m39t/1/
to move an element out of flow and position it depending of the viewport use: position: fixed;
svg {
position: fixed;
bottom: 0;
}
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 120" preserveAspectRatio="none">
<path d="M321.39,56.44c58-10.79,114.16-30.13,172-41.86,82.39-16.72,168.19-17.73,250.45-.39C823.78,31,906.67,72,985.66,92.83c70.05,18.48,146.53,26.09,214.34,3V0H0V27.35A600.21,600.21,0,0,0,321.39,56.44Z" class="shape-fill"></path>
</svg>
Try this:
html, body {height: 100vh;}

SVG to make a wave effect border and allow it to stretch horizontally only

I have used https://getwaves.io/ to create a wave SVG.
So I have added this svg to my header element:
.page{
height:400px;
width:100%;
background: green;
}
.pls-sticky-header{
position: relative;
height: 150px;
background-color: red;
}
.wave{
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
<div class="page">
<div class="pls-sticky-header">
<svg viewBox="0 0 1440 200" class="wave">
<path fill="#ffffff" fill-opacity="1" d="M0,128L40,117.3C80,107,160,85,240,90.7C320,96,400,128,480,154.7C560,181,640,203,720,192C800,181,880,139,960,106.7C1040,75,1120,53,1200,58.7C1280,64,1360,96,1400,112L1440,128L1440,320L1400,320C1360,320,1280,320,1200,320C1120,320,1040,320,960,320C880,320,800,320,720,320C640,320,560,320,480,320C400,320,320,320,240,320C160,320,80,320,40,320L0,320Z"></path>
</svg>
</div>
<div class="content"></div>
</div>
```
Currently as the window gets larger in size - waves get more space in height - but I don't want such behavior.
I want to make waves get 30% of the header in height, and 100% of width (make them stretch only horizontally), but I'm struggling with it.
Maybe there is an option to make such border for a DIV vlock if it not possible to achieve using SVG.
Simply add preserveAspectRatio="none"
.page {
height: 400px;
width: 100%;
background: green;
}
.pls-sticky-header {
position: relative;
height: 150px;
background-color: red;
}
.wave {
position: absolute;
bottom: 0;
height:30%;
left: 0;
width: 100%;
}
<div class="page">
<div class="pls-sticky-header">
<svg viewBox="0 0 1440 200" class="wave" preserveAspectRatio="none">
<path fill="#ffffff" fill-opacity="1" d="M0,128L40,117.3C80,107,160,85,240,90.7C320,96,400,128,480,154.7C560,181,640,203,720,192C800,181,880,139,960,106.7C1040,75,1120,53,1200,58.7C1280,64,1360,96,1400,112L1440,128L1440,320L1400,320C1360,320,1280,320,1200,320C1120,320,1040,320,960,320C880,320,800,320,720,320C640,320,560,320,480,320C400,320,320,320,240,320C160,320,80,320,40,320L0,320Z"></path>
</svg>
</div>
<div class="content"></div>
You can give a height attribute to the svg. Right now it is modifying the height to match the width. Don't use percentages for the height. because it will change with screen size.

How to scale a polygon svg with an image fill to the container's height?

I'd like to scale an SVG with a polygon shape to the full height of the container. Setting the SVG's height to 100% wouldn't work.
Relevant jsFiddle: https://jsfiddle.net/12yktprj/
Following line is causing me trouble:
aside svg {
height: 100%; /* somehow not working */
width: 100%; /* somehow not working */
}
The svg element need to have a viewBox attribute and no width and height. For the viewBox attribute I'm taking the size of the polygon.
Also in this case (flex-direction:row - the default) instead of declaring the width of the flex items I'm declaring the [flex property]
The aside has position:relative; and the svg has position:absolute; and overflows the aside. I hope this is what you were asking.
(https://developer.mozilla.org/en-US/docs/Web/CSS/flex)
*{padding:0,margin:0}
body {
height: 300px;
width: 900px;
border: 3px solid green;
padding: 0;
display: flex;
justify-content: space-between;
align-items: stretch;
position:relative;
background:#ddd;
}
aside {
position:relative;
flex: 1 1 25%;
height: 100%;
border: 1px solid blue;
}
aside svg {
position:absolute;
height:100%
}
article {
border: 2px solid orange;
flex: 1 1 75%;
height: 100%;
padding: 2px;
}
<body>
<aside>
<svg viewBox="0 0 100 100">
<defs>
<pattern id="pattern1" height="100%" width="100%" patternContentUnits="objectBoundingBox">
<image height="1" preserveAspectRatio="slice" xlink:href="https://i.imgur.com/8OtgM8B.jpg" />
</pattern>
</defs>
<polygon fill="url(#pattern1)" points="0,0 70,0 100,100 0,100"/>
</svg>
</aside>
<article>
<h1>Title</h1>
<p>Sample Text</p>
</article>
</body>

cropping a photo using css

I need to crop quadrilateral for a photo. I need parallelogram. But it is skewed. I need a parallelogram crop. How can I do it?
Code is below:
img {
transform: skew(-10deg);
position:relative;
left: 30px;
}
<img src="http://blogs.villagevoice.com/runninscared/RL%20Gang%20Boy.jpg">
What i want is i dont want boy to turn sideways but only the picture to crop. Thank you.
You could use svg's clipPath and foreignObject to apply inline clip-path for maximum browser support.
<svg width="300" height="400">
<defs>
<clipPath id="parallelogram">
<path d="M50,0 h250 l-50,400 h-250z" />
</clipPath>
</defs>
<foreignObject clip-path="url(#parallelogram)" width="100%" height="100%">
<img src="http://blogs.villagevoice.com/runninscared/RL%20Gang%20Boy.jpg" />
</foreignObject>
</svg>
please try this css + html script
CSS
#graphic {
width: 200px;
height: 100px;
position: relative;
}
#graphic:before {
content: '';
position: absolute;
width: 200px;
height: 50px;
z-index: -1;
background-image: url(http://blogs.villagevoice.com/runninscared/RL%20Gang%20Boy.jpg`enter code here`); /* Image is 500px by 500px, but only 200px by 50px is showing. */
}
HTML
<div id="graphic">lorem ipsum</div>

CSS: make div width proportional to height

This is a little tricky to explain, but: I want a responsive-height div (height: 100%) that will scale the width proportional to the height (not vice versa).
I know of this method utilising a padding-top hack to make the height proportional to the width, but I need it to work the other way around. Having said that, I'm not hugely keen on the additional requirement of absolutely-positioned elements for the content in that method, so I realise I may well be asking for the moon on a stick here.
To help visualise, here is an image:
...and here is a jsFiddle, illustrating pretty much the same thing.
It is worth noting that I am already using the :before and :after pseudo-elements to vertically-align the content of the box I want to scale proportionally.
I would really enjoy not having to revert to jQuery, just because there's going to be an inherent requirement for resize handlers and generally more debugging all round... but if that's my only choice, then fiat.
I've been wondering about a pure-css solution to this problem for a while. I finally came up with a solution using ems, which can be progressively enhanced using vws:
See codepen link for full working demo and explanation:
http://codepen.io/patrickkunka/pen/yxugb
Simplified version:
.parent {
font-size: 250px; // height of container
height: 1em;
}
.child {
height: 100%;
width: 1em; // 100% of height
}
Oh,you could probably use that "padding-top" trick.
width: 50%;
height: 0;
padding-bottom: 50%;
http://absolide.tumblr.com/post/7317210512/full-css-fluid-squares
Or:
.square-box{
position: relative;
width: 50%;
overflow: hidden;
background: #4679BD;
}
.square-box:before{
content: "";
display: block;
padding-top: 100%;
}
http://codeitdown.com/css-square-rectangle/
The vertical padding in CSS is related to the width of the element, not the height.
The font solution requires that the height is known. I have found a solution for making an element proportional inside a parent div with unknown widths and heights. Here is a demo.
The trick I'm using is to have an image used as a spacer. The code explained:
<div class="heightLimit">
<img width="2048" height="2048" class="spacer"
src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAA
P///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">
<div class="filler">
<div class="proportional">
</div>
</div>
</div>
So it is not the prettiest with two extra divs and a useless image. But it could be worse. The image element needs to have width and height with the desired dimensions. Width and height need to be as large as the maximum size allowed (a feature!).
The css:
.heightLimit {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: auto;
max-width: 100%;
overflow: hidden;
}
This element is to limit the height, but to expand horizontally (width: auto) although never beyond the parent (max-width). Overflow needs to be hidden because some children will protrude outside the div.
.spacer {
width: auto;
max-height: 100%;
visibility: hidden;
}
This image is invisible and scaled proportionally to the height, while the width is adjusted and forces the width of the parent to also be adjusted.
.filler {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
This element is required to fill the space with an absolutely positioned container.
.proportional {
position: relative;
width: 100%;
height: 0;
padding-bottom: 100%;
}
And here our proportional element gets a height proportional to the width with the familiar padding-bottom trick.
Unfortunately, there is a bug in Chrome and IE so if you modify the parent element using Javascript, such as in my demo, the dimensions will not be updated. There is a hack that can be applied to solve that, as shown in my demo.
You can use view height (vh) as the unity for the width.
Here is an example with the 20px margin you asked for.
.parent {
margin : 20px;
}
.child {
width: calc(100vh - 40px);
height : calc(100vh - 40px);
margin:0 auto;
background: red;
box-sizing:border-box;
padding:10px;
}
See the fiddle :
https://jsfiddle.net/svobczp4/
Based off of #kunkalabs's answer (which is really smart) I've come up with a solution that lets you preserve the inherited font-size.
HTML:
<div id='rect'>
<div id='content'>Text</div>
</div>
CSS:
#rect {
font-size: 1000%;
height: 1em;
width: 1em;
position: relative;
}
#content {
font-size: 10%;
}
So basically the font-size of #content is (100 / $rectFontSize) * 100 percent of the rectangle. If you need a definite pixel size for the rectangle, you can set the #rect's parent's font-size…otherwise just adjust the font-size until it's about where you want it to be (and enrage your designer in the process).
You can achieve that by using SVG.
It depends on a case, but in some it is really usefull. As an example - you can set background-image without setting fixed height or use it to embed <iframe> with ratio 16:9 and position:absolute.
For 3:2 ratio set viewBox="0 0 3 2" and so on.
Example:
div{width:35%;background-color:red}
svg{width:100%;display:block;visibility:hidden}
<div>
<svg viewBox="0 0 3 2"></svg>
</div>
On newer browsers, we can use aspect-ratio with a fixed height, and the width will be calculated accordingly.
img {
aspect-ratio: 1.2;
height: 250px;
max-width: 500px;
}
But the browser support for aspect-ratio is not good enough. I liked the SVG solution proposed by #Jakub Muda, except for the fact that it requires modifying the markup. I have moved the SVG to CSS by including it using content property. On newer browsers, it disables the SVG hack and switches to aspect-ratio property.
document.querySelector('.nav').addEventListener('click', function(e) {
var index = parseInt(e.target.dataset.index);
if (!index) {
return;
}
var elements = document.querySelectorAll('.box');
for (var i = elements.length; i > 0; i--) {
elements[i - 1].classList.toggle('hide', i !== index);
}
});
.wrapper {
max-width: 500px;
margin: 0 auto;
width: 100%;
height: 250px;
text-align: center;
background: green;
}
.box {
display: inline-flex;
position: relative;
max-width: 100%;
}
/* SVG Hack */
.box::before {
display: block;
line-height: 0;
max-width: 100%;
content: 'test';
}
[data-aspect-ratio="1"]::before {
content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 1' height='250'></svg>");
}
[data-aspect-ratio="2"]::before {
content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 1' height='250'></svg>");
}
[data-aspect-ratio="3"]::before {
content: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 3 1' height='250'></svg>");
}
#supports (aspect-ratio1: 1) {
/* Modern browsers */
.box {
height: 100%;
background: green;
}
.box::before {
display: none;
}
[data-aspect-ratio="1"] {
aspect-ratio: 1;
}
[data-aspect-ratio="2"] {
aspect-ratio: 2;
}
[data-aspect-ratio="3"] {
aspect-ratio: 2;
}
}
.content {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.content>svg {
display: block;
width: 100%;
position: absolute;
top: 50%;
left: 50%;
height: auto;
transform: translate(-50%, -50%);
}
.nav {
text-align: center;
}
.hide {
display: none;
}
<!doctype html>
<html lang="en">
<head>
<title>Width proportional to height in CSS</title>
</head>
<body>
<div class="wrapper">
<div class="box" data-aspect-ratio="1">
<div class="content">
<svg viewBox="0 0 100 100" width="100" height="100" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="96" height="96" style="fill:#DEDEDE;stroke:#555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="#555555">100×100</text></svg>
</div>
</div>
<div class="box hide" data-aspect-ratio="2">
<div class="content">
<svg viewBox="0 0 200 100" width="200" height="100" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="196" height="96" style="fill:#DEDEDE;stroke:#555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="#555555">200×100</text></svg>
</div>
</div>
<div class="box hide" data-aspect-ratio="3">
<div class="content">
<svg viewBox="0 0 300 100" width="300" height="100" xmlns="http://www.w3.org/2000/svg"><rect x="2" y="2" width="296" height="96" style="fill:#DEDEDE;stroke:#555555;stroke-width:2"/><text x="50%" y="50%" font-size="18" text-anchor="middle" alignment-baseline="middle" font-family="monospace, sans-serif" fill="#555555">300×100</text></svg>
</div>
</div>
</div>
<div class="nav">
<button data-index="1">1</button>
<button data-index="2">2</button>
<button data-index="3">3</button>
</div>
</body>
</html>
Make the parent DIV behave like a table cell and align the child element vertically. No need to do any padding tricks.
HTML
<div class="parent">
<img src="foo.jpg" />
</div>
CSS
.parent { width:300px; height:300px; display:table-cell; vertical-align:middle; }