I've got some layers of divs with svg backgrounds. Set at 100% width and auto height:
<div class="group section hot-bonus">
<div class="layer layer-base clouds"></div>
<div class="layer layer-back1 clouds-1"></div>
<div class="layer layer-back2 clouds-2"></div>
<div class="layer layer-back3 clouds-3"></div>
<div class="layer layer-back5 bg"></div>
</div>
The .group has these styles:
height: 65%;
z-index: 8;
text-align: center;
All of the clouds follow this format:
.clouds {
z-index: 6;
background: url(../images/hot_bonus_clouds.svg) center bottom no-repeat;
background-size: 100% auto;
#include transform( scale(1.1) );
}
The result is this (full width browser screenshot):
However, I can't seem to get it working on IE10. This is what it's giving me (never mind the design/layout differences, just the unstretched cloud backgrounds):
And this is despite IE10 showing that they have the style background-size: 100% auto; applied.
Any ideas what's going on?
Answer found here: https://stackoverflow.com/a/22970897/1192861
Be sure that your SVG has a width and height
I generated my SVG's from illustrator, I had to open them up again and set a width/height for each one. A really quick way to set it was to pay attention to this part of the svg element:
viewBox="0 0 1428.5 521.8" where 1428.5 is the width and 521.8 is the height. So the fix makes sure the SVG element looks something like this:
<svg viewBox="0 0 1428.5 521.8" width="1428.5" height="521.8"....>/***/</svg>
Related
I am trying to achieve the following design:
https://imgur.com/a/iXhOTfR
My problem is that I don't want to use a png image as it is too large. Is there another way of achieving the cut image effect?
I am using a SVG file for the left blue part. This is what I achieved so far: https://imgur.com/a/bZSjOUH
Here is my HTML:
<section class="section">
<div class="section-mask">
SVG FILE
</div>
<div class="container-full">
<div class="row">
<div class="col-lg-6 column-text">
<h2 class="title">
Section Title
</h2>
<div class="paragraph">
Section Content
</div>
</div>
<div class="col-lg-6 column">
Section Widget
</div>
</div>
</div>
</section>
If I understand you correctly, you want to achieve something like multiple angled cuts with varying images and background colors. You can do this with something like the following, tailoring it to your needs, and through experimentation swap in different solutions but using the same basic tools.
These tools largely comprise:
clip-path, &
linear-gradient
This solution will provide a close match to the effect, but adapt to the users viewport. But in adapting, be aware that angles will necessarily change (but it should feel natural and fluid, unlike a fixed image that scales and feels unnatural as the viewport changes).
Clip path can be used to give shape to an element, and while the logic for "drawing" the desired shape can be tricky, Bennett Feely has a great tool called Clippy to work out the code.
Here's the 'cut design' demo on CodePen, and I'll include the working code here, as well, with a brief explanation.
The HTML is written assuming that this is part of a visual treatment for a page header, but adapt as needed. The CSS is a quick and dirty mock-up with clip-path arranged in a way to make the number pairs easy to scan and adjust at a glance:
header {
background-image: url(//unsplash.it/1600x900);
background-size: cover;
}
.cut-container {
background-image: linear-gradient(80deg, hsla(180, 100%, 40%, .5) 44.9%, white 45.1%);
}
.cut {
background: url(//unsplash.it/1600x600) center center;
background-size: cover;
clip-path: polygon(
0 0,
100% 0,
100% 70%,
0 100%
);
height: 20em;
}
.cut2 {
background: hsl(220,50%,30%);
clip-path: polygon(
50% 95%,
100% 25%,
100% 100%,
0 100%,
0 25%);
height: 15em;
}
<header>
<div class="cut-container">
<div class="cut"></div>
<div class="cut2"></div>
</div>
</header>
Clip-path is here used to make a polygon, and the number pairs indicate where to position the corners. Each pair corresponds to the number of angles in the shape, so one is a trapezoid, and the other is essentially an odd pentagon in a sort of M shape.
The middle bit is achieved with a hard linear-gradient over a background image. This is all done with random images drawn from the Unsplash API, but you could do something with background position, for example, and use whatever images you're working with in appropriate sizes and eliminate the large bandwidth issues in this rough demo.
Finally, note that for an angled linear-gradient with a sharp cut, most monitors will produce a jagged edge. To effect anti-aliasing and the appearance of a smooth edge, use values that are close but not exact. Here, .cut-containeruses 44.9% and 45.1%, which looks smooth.
With a little more work and appropriately sized images, you can use some of these techniques to build the kind of design you're after with pure CSS and without complex transforms or images that don't adapt to viewport. The support isn't bad on this for modern browser, and those that lack support will ignore the clip-path and fall back to solid blocks, which I really believe is better than fighting through a complex solution for a cosmetic effect, or making high rendering demands of older browsers.
How about making a rotated css block that overlays the image while staying below the svg?
body {
overflow-x: hidden;
}
.image {
background: grey;
width: 100%;
height: 100px;
}
.cut {
border: 1px solid red;
width: 200%;
height: 150px;
transform: rotate(-5deg);
background: white;
padding: 50px;
transform-origin: 0% 50%;
position: absolute;
}
.svg {
border: 1px solid green;
position: relative;
z-index: 1;
}
<div class="image">This would be the image</div>
<div class="cut">This is the CSS block</div>
<div class="svg">This would be the SVG</div>
I'm working on a website, where the structure of a section is like this:
<div class="col-md-6">
<section class="right" data-type="background" data-speed="30" style="background: url(<?php echo get_field('book_image')['url']; ?>);">
</section>
</div>
The parent div in this situation has (in safari) a height 2976px. However, the child won't size itself to the same height, even though I've applied the height property to it.
I tried this in Chrome & Safari, both on macOS: Chrome worked, Safari didn't.
Is there any was to get this to work, preferably without any JS? Thanks :)
-- Edit
I'm using Bootstrap4, however, the right class only contains properties to style the div. Contents below
.right {
max-width: 50vw;
height: 100%;
background-size: 60vh !important;
background-repeat: no-repeat;
}
-- Edit #2.
Here's a snippet demonstrating the problem:
.left {
padding: 0;
background: #000; /*debugging*/
height: 200px; /*debugging*/
}
.right {
height: 100%;
background-size: 60vh !important;
background-repeat: no-repeat;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet" />
<div class="container-fluid">
<div class="row">
<div class="col-6 left">
</div>
<div class="col-6">
<section class="right" data-type="background" data-speed="30" style="background: red;"></section>
</div>
</div>
</div>
(or in JSFiddle: Click me
As an advice you can use webpage CANIUSE
,you can check which css property does browser support . In my opnion the best solution is to use jquery or javascript to set height of div , when page will be resize or will be load. You can't find absolute perfect solution to solve crossbrowser support . If you need help with jquery do not hesitate ask when you need .
The problem is your parent div doesn't have an height property. Even though Chrome is able to resolve the containers height, Safari (and maybe some other browsers) isn't. In order to fix this you've to specify a height for the 2nd div in your .row (the parent of .right) as well.
Styling
.right-parent {
height: 200px;
}
Markup
<div class="col-6 right-parent">
<section class="right" data-type="background" data-speed="30" style="background: red;"></section>
</div>
Demo
Original Question
What is the most efficient way to calculate the width of an image relative to it's containing div in css?
I have the following snippet which sets #image1.width to a percentage that is relative to the width of its parent. I'm using a percentage because I need the image to scale proportionately to the parent when the screen is resized.
div {
position: relative;
display: block;
width: 100%;
}
#image1 {
position: absolute;
left: 10%;
top: 10%;
width: 29.43%;
height: auto;
}
#under {
width: 100%;
}
<div>
<img id="image1" src="http://placehold.it/206x115">
<img id="under" src="http://placehold.it/700x300/ff00f0/ffffff">
</div>
It is currently working as intended, except that I have to manually calculate the width percentage for every single image. i.e.
#image1 dimensions == 206x115
#under dimensions == 700x300
new #image1.width % == #image1.width / #under.width == 206/700 == ~29.43%
What I want to know is if there id a calc() method or similar I can implement to ease/streamline this process?
I was going to use width: calc(100% / 700) however this obviously will not work when the screen size changes.
Goals
To re-iterate, it is imperative that the #under image scales with the screen size and the #image remains proportionate.
I want the natural image ratios preserved with one another (i.e. an image that is one quarter the size of the other will remain as such at all browser widths).
Note: The html can be reconfigured in any way to achieve this.
Target browsers: Chrome, Firefox, Edge.
Post Bounty Review
Comment on #Obsidian Age's answer (end of first bounty 31.03.17):
Unfortunately #Obsidian Age's answer is not correct - it is close but not quite and I just wanted to clarify this here... Below is a snippet from his answer... Note that I think it is a good answer, just clarifying why it has not been accepted:
:root {
--width: 90vw; // Must be viewport-driven
}
#image1 {
width: calc(var(--width) / 3); // The 3 can be replaced with any float
}
Setting --width: 90vw what happens if body or div have a max-width set? This is also very hard to calculate for all devices when factoring in viewport-scaling.
#image1 { width:calc(var(--width) / 3); } This equates to calc(90vw / 3) which is 30vw which would equate to 30% of the images width. But how do we work out the number to divide by? Well it's back to where we started... width:calc(var(--width) * calc(206/700*100)); And this is why I have not accepted this answer.
Unfortunately, CSS has no parent selector. While you can't make an element relative to the parent directly with CSS, what you can do with pure CSS is set a variable that both elements make use of:
:root {
--width: 90vw; // Must be viewport-driven
}
Now you can use this variable as both the (fixed) width of the parent element, and the calculation-driven width of the child:
#under {
width: var(--width);
}
#image1 {
width: calc(var(--width) / 3); // The 3 can be replaced with any float
}
Note that the variable must either be a fixed unit, or be relative to the viewport. If it were percentage-based, both #under and #image1 would base their width off of their respective parents. In order to have this work responsively, it must be based off of the viewport.
:root {
--width: 90vw;
}
div {
position: relative;
display: block;
width: 100%;
}
#image1 {
position: absolute;
left: 10%;
top: 10%;
width: calc(var(--width) / 3);
height: auto;
}
#image2 {
position: absolute;
left: 25%;
top: 10%;
width: 10%;
height: auto;
}
#under {
width: var(--width);
}
<div>
<img id="image1" src="http://placehold.it/206x115">
<img id="under" src="http://placehold.it/700x300/ff00f0/ffffff">
</div>
I've also created a JSFiddle of this here, where you can see both elements scale when the viewport resizes.
Hope this helps! :)
I realize that the question prompts for a pure CSS solution, but I liberally interpreted that as meaning "no JavaScript".
In that vein, here's a solution using an embedded SVG:
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" viewBox="0 0 700 300">
<image x="0" y="0"
xlink:href="http://placehold.it/700x300/ff00f0/ffffff"/>
<image x="10%" y="10%"
xlink:href="http://placehold.it/206x115"/>
</svg>
The best approach I think would be to eliminate width & use scale to fit the div, but the problem is scale transform do not accept any unit value, such as % or px or vw/vh!
.common_img_class{
transform: scale(calc(100vw/700)); /* this won't work! */
/* Idea here is to let image take is original width & then scale with respact to base image scaling. Base image scaling is detenined by *window_width/base_image _width*, here base image width is 700 as per you example */
}
Thus second best I can think of is to eliminate manual calculation of percent. Use calc() function to do that for you.
#firsrt_img{
width: calc((206/700) * 100%);
}
#second_img{
width: calc((306/700) * 100%);
}
Here you still have to write width for all but atleast spared from percent or ratio calculation.
Note:
If anyone can help with first approach, their inputs are welcome.
One thing that might work, if you are willing to use bootstrap (https://getbootstrap.com/examples/grid/):
<!-- parent -->
<div class="row">
<div class="col-md-6">
<img src="">
<!-- this is 50% of the screen for min 992px, a full line otherwise -->
</div>
<div class="col-md-3">
<img src="">
<!-- this is 25% of the screen for min 992px, a full line otherwise-->
</div>
<div class=col-md-3>
<img src="">
<!-- this is 25% of the screen for min 992px, a full line otherwise -->
</div>
</div>
You can group these as you want/need, just remember that the numbers have to add to 12 (in my example, 6+3+3). You can achieve a 100% width effect using col-md-12. Also, the md infix is just one of several options of cutoff between putting everything on the same line and stacking elements. You can check out http://getbootstrap.com/css/#grid for more details, as well as a couple of examples.
Inspired by the answer of Robby Cornelissen, here is an approach that works in the targeted browsers currently. Its only drawback is that the dimensions of the images have to be specified in the HTML (well, the SVG really) explicitly.
Here is a demo.
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" viewBox="0 0 700 300">
<image x="0" y="0" width="700" height="300"
xlink:href="http://placehold.it/700x300/ff00f0/ffffff"/>
<image x="10%" y="10%" width="206" height="115"
xlink:href="http://placehold.it/206x115"/>
</svg>
The approach, like Robby's answer, uses the SVG image element. That currently defaults to having zero width and height when no dimensions are specified explicitly, but will change in SVG 2. This means that as soon as SVG 2 is supported by browsers, instead of specifying the image dimensions, we could set width="auto" height="auto" and be done.
The value auto for width and height on the ‘image’ element is calculated from the referenced image's intrinsic dimensions and aspect ratio, according to the CSS default sizing algorithm.
— SVG 2 Editor's Draft, § 7.8. Sizing properties: the effect of the ‘width’ and ‘height’ properties. Accessed 2017-12-18.
I'm making a basic header using divs and a nested img in a fluid layout. I'm a bit rusty on this and i can't for the love of me figure out how to ensure that the image nested in the div scales without scaling to the point where it becomes smaller its parent div.
EDIT: Updated the codepen link showing how using min-height won't work as it squeezes the image
HTML:
<div class="container">
<div class="item half">
<p>
Some text
</p>
</div>
<div class="item half">
<img src="http://dummyimage.com/hd1080" class="full-width">
</div>
</div>
CSS:
.container{
margin: 0 auto;
max-width: 1920px;
}
.item{
height: 300px;
float:left;
overflow: hidden;
background-color: gray;
}
.half{
width: 50%
}
.full-width{
max-width: 100%;
}
And for good measure a quick illustration of what is happening:
And an illustration of what i want to happen:
Edit: Note that the image here is not being squeezed, which is what happens if you set the image to have a min-height equal to its parent div. But rather the overflow is hidden. You can also see that i do not mind the images being cropped.
Any help appreciated.
You can add min-height equal to the div.item height to your image CSS
img {
max-width:100%;
min-height:300px;
}
I've managed to find the solution i wanted in this thread. The function i was looking for was object-fit.
I've used the following solution:
img{
min-height: 100%;
object-fit: cover;
}
Edit: quickly found out that this property is only properly supported by Firefox, Chrome and Opera. Use this polyfill to fix this on Safari and IE.
Taking a look at the code below and the fiddle, can some please tell my why in IE (9-10-11) the height of the svg image is not matching the height of the sibling (content on right) like in chrome, FF, Safari?
In IE there is extra vertical space in the left table-cell.
Thank-you
HTML
<div class="table-layout">
<div class="table-cell fixed-width">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 180.22 150.718" enable-background="new 0 0 180.22 150.718" xml:space="preserve">
<circle fill="#E3E3E3" cx="91.5" cy="75.167" r="75.167" />
</svg>
</div>
<div class="table-cell" style="border: solid red 1px">
<div class="row">
<div class="col-xs-12">content</div>
</div>
<div class="row">
<div class="col-lg-6">
<div class="row">
<div class="col-sm-6">content</div>
<div class="col-sm-6">content</div>
</div>
</div>
<div class="col-lg-6">content</div>
</div>
</div>
CSS
.table-layout {
display: table;
width: 100%;
table-layout: fixed;
}
.table-layout .table-cell {
display: table-cell;
border: solid 1px #ccc;
vertical-align: top;
}
.fixed-width {
vertical-align: middle !important;
background-color: #a3a3a3;
width: 60px;
padding: 5px;
}
fiddle: http://jsfiddle.net/gp2nqzh0/1/
Remove width:100%; from .table-layout and it will work fine.
This is an old post but still relevant.
For those of you that don't have IE (hopefully most) or an emulator and want to see the issue, I've attached a screenshot.
Fix: set both a height and width on your svg element.
.fixed-width svg {
width: 60px;
height: 60px;
}
I tested your fiddle on IE 11 using Browserstack and can confirm it works. Setting max-width and max-height attributes also works.
WHY is this happening?
I recommend reading this article to fully understand the behavior of svgs in browsers: https://css-tricks.com/scale-svg/ BONUS: This also has solutions for many scenarios.
BUT for this case, your answer is below (from the article),
Many browsers—IE, Safari, and versions of Opera and Chrome released prior to summer 2014—will not auto-size inline SVG. If you don't specify both height and width, these browsers will apply their usual default sizes, which as mentioned previously will be different for different browsers. The image will scale to fit inside that height or width, again leaving extra whitespace around it. Again, there are also inconsistencies in what happens if you leave both height and width auto.
Internet Explorer cuts the difference, using width of 100% and height of 150px for images and inline SVG.
Because you have a fixed-width class on your div, I assume you don't need to worry about scalability and setting the fixed width and height on the svg will suffice.