White stripe on top of SVG on some screensizes? - css

I have a colored div followed by an svg. When changing my browser window, sometimes a small white line appears. How can I get rid of it?
.wave {
background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"><path fill="red" d="M0,96L80,85.3C160,75,320,53,480,90.7C640,128,800,224,960,266.7C1120,309,1280,299,1360,293.3L1440,288L1440,0L1360,0C1280,0,1120,0,960,0C800,0,640,0,480,0C320,0,160,0,80,0L0,0Z"/></svg>');
height:180px;
background-size:100%;
background-repeat: no-repeat;
margin-top:-20px;
background-color:white;
}
<div style="background-color:red;width:100%;height:100px">
</div>
<div class="wave">
hallo
</div>

These are rounding artefacts that cannot be avoided. background-color:white introduces a white rectangle behind the svg, but on top of the top div that might be slightly too large. Remove it, and the svg content will sit directly on top of the div.
If you need an explicitely white background, apply it to an element that sits behind both the top div and the svg. For example like this, avoiding an extra DOM object:
.top {
position: relative;
background-color:red;
width:100%;
height:100px;
}
.top::after {
content: "";
position: absolute;
top: 100%;
width:100%;
height:180px;
z-index: -1;
background-color:white;
}
.wave {
background-image: url('data:image/svg+xml;charset=UTF-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"><path fill="red" d="M0,96L80,85.3C160,75,320,53,480,90.7C640,128,800,224,960,266.7C1120,309,1280,299,1360,293.3L1440,288L1440,0L1360,0C1280,0,1120,0,960,0C800,0,640,0,480,0C320,0,160,0,80,0L0,0Z"/></svg>');
height:180px;
background-size:100%;
background-repeat: no-repeat;
margin-top:-20px;
}
<div class="top">
</div>
<div class="wave">
hallo
</div>

Related

Responsive irregular background shape with CSS

I have been trying to achieve the same result as shown in the image with plain CSS.
I have tried using a background image (cover...), but it's not responsive (cuts the shape)
I managed to get a similar result with clip-path but not the round corners, and also is not supported with all browsers.
.shape {
background:#16489F;
clip-path: polygon(5% 0, 95% 0, 100% 50%, 95% 100%, 5% 100%, 0% 50%);
}
What I'm aiming for:
Thank you very much
Here is an idea based on this previous answer:
.box {
margin:20px auto;
font-size:22px;
min-width:200px;
display:table;
padding:10px 30px;
box-sizing: border-box;
text-align:center;
color:#fff;
position:relative;
z-index:0;
}
.box::before,
.box::after,
.box span::before,
.box span::after{
content:"";
position:absolute;
z-index:-1;
top:0;
left:0;
right:50%;
bottom:50%;
background:#16489F;
border-radius:10px 0 0 0;
transform:var(--s,scaleX(1)) skew(-35deg);
transform-origin:right bottom;
}
.box::after {
--s:scalex(-1);
}
.box span::before {
--s:scaleY(-1);
}
.box span::after {
--s:scale(-1);
}
<div class="box"><span></span> some text here</div>
<div class="box"><span></span> more and more <br> text here</div>
<div class="box"><span></span> even more <br> and more <br> text here</div>
<div class="box"><span></span> long long loooooonooooog text <br> and more <br> text here</div>
Like below if you want the radius on the edges:
.box {
margin:20px auto;
font-size:22px;
min-width:200px;
display:table;
padding:10px 30px;
box-sizing: border-box;
text-align:center;
color:#fff;
position:relative;
z-index:0;
}
.box::before,
.box::after,
.box span::before,
.box span::after{
content:"";
position:absolute;
z-index:-1;
top:0;
left:0;
right:50%;
bottom:calc(50% - 5px);
background:#16489F;
border-radius:10px 0 0 11px;
transform:var(--s,scaleX(1)) skew(-35deg);
transform-origin:100% calc(100% - 5px);
}
.box::after {
--s:scalex(-1);
}
.box span::before {
--s:scaleY(-1);
}
.box span::after {
--s:scale(-1);
}
<div class="box"><span></span> some text here</div>
<div class="box"><span></span> more and more <br> text here</div>
<div class="box"><span></span> even more <br> and more <br> text here</div>
<div class="box"><span></span> long long loooooonooooog text <br> and more <br> text here</div>
An element can have multiple background images so you could use images for the end caps and a matching color fill for the actual content area.
This demo is rough but it demonstrates the idea. I've left the fill an obviously different color to make it easier to see what's what. I'm using quick screenshots of your sample image and I caught a bit of the edge, causing the lines extending from the caps. But you get the idea.
.demo {
padding: 24px 72px;
color: white;
background-color: skyblue;
background-image:
url(https://i.imgur.com/LocAlN0.png),
url(https://i.imgur.com/zXDA91q.png);
background-repeat: no-repeat;
background-size: contain;
background-position: 0 center, center right;
}
<div class="demo">
Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots.
</div>
I would use 3 divs, first and last with background-images (the irregular shape) and the one in the middle with background-color instead.

How to modify CSS heart to insert inside image?

So I have heart on CSS.
But now I want to modify it and add inside dynamic image.
Here is what I have:
.heart {
position: relative;
width: 100px;
height: 90px;
float: left;
width: 100px;
height: 90px;
overflow: hidden;
}
.heart.right {
left: auto;
right: 0;
}
.heart:before,
.heart:after {
position: absolute;
content: '';
left: 50px;
top: 0;
width: 50px;
height: 80px;
background: #fc2e5a;
border-radius: 50px 50px 0 0;
transform: rotate(-45deg);
transform-origin: 0 100%;
}
.heart:after {
left: 0;
transform: rotate(45deg);
transform-origin: 100% 100%;
}
Here is my fiddle: https://jsfiddle.net/9g1qswdd/
All the existing answers help you to place an image on top of a heart shape but not crop or cut it into a heart shape. The only existing answer that would help you achieve the latter is the clip-path model but that code produces a different output shape (its probably more a sample on how to do than a direct answer to your question).
For inserting an image in to the heart shape (I assume you mean cutting the image into a heart shape), don't use your existing approach. It is very tough because you that CSS method creates the shape by using two rotated elements. So, you'd have to go through the pain of - (a) split the image into two bits (b) place each half on each side (c) reverse rotate the images to nullify the effect the initial rotation that was set on the element (d) set background-position for each half of the image such that they match accurately etc. Even after going through all these troubles, you'd still face problems when the image is dynamic because setting background-position via percentage value work a lot more differently than what we think.
Use SVG: SVG is the recommended tool for creating such complex shapes with a background that is not a solid color.
With SVG, we can easily create complex shapes using the path element and also add an image as background or fill. SVGs are scalable and so are highly useful in responsive design. Using SVGs also allow us greater control over the shape itself.
Below is a heart shape that is created using SVG and having an image inserted into it as background.
svg {
height: 200px;
width: 200px;
}
path {
fill: url(#bg-image);
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg viewBox='0 0 100 100'>
<defs>
<pattern id='bg-image' width='1' height='1' patternUnits='objectBoundingBox'>
<image xlink:href='https://placeimg.com/100/100/nature/7' width='100' height='100' />
</pattern>
</defs>
<path d='M50,90 L20,60
A15,15 0 0,1 50,30
A15,15 0 0,1 80,60 z' />
</svg>
Below is a very short explanation of what the commands used in the path element's d attribute do. A more detailed explanation can be found in this MDN page:
M - Moves pen to the point specified by the coordinate given immediately after the command.
A - Draw an arc with the specified X and Y radius, ending at the point specified after command.
L - Draw a straight line from one specified point to another.
z - Close the path by drawing a straight line from path's last point to its first point.
You can also use a SVG based clip-path definition to clip the image like in the below snippet but the browser support for clip-path is lower.
img {
-webkit-clip-path: url(#clipper);
clip-path: url(#clipper);
}
body {
background-image: radial-gradient(circle, #3F9CBA 0%, #153346 100%);
}
<svg viewBox='0 0 100 100' height='0' width='0'>
<defs>
<clipPath id='clipper' clipPathUnits='objectBoundingBox'>
<path d='M.50,.90 L.20,.60
A.15,.15 0 0,1 .50,.30
A.15,.15 0 0,1 .80,.60 z' />
</clipPath>
</defs>
</svg>
<img src='https://placeimg.com/100/100/nature/7' />
<img src='https://placeimg.com/200/200/nature/7' />
Assuming that the heart is to be placed on a solid background, you can hide selectively the image with several gradients placed on the pseudo elements.
This has the advantage of enabling the use of cover or contain on the background image size:
.heart2 {
width: 300px;
height: 300px;
background-image: url(http://lorempixel.com/400/200);
background-size: cover;
position: relative;
border: solid 1px red;
}
.heart2:before {
content: '';
position: absolute;
width: 450px;
height: 450px;
left: -75px;
top: 75px;
transform: rotate(45deg);
background-image: linear-gradient(white, white), linear-gradient(white, white);
background-size: 50%;
background-repeat: no-repeat;
background-position: right top, left bottom;
}
.heart2:after {
position: absolute;
width: 114%;
height: 114%;
content: '';
left: -21px;
bottom: 70px;
transform: rotate(45deg);
background-image: radial-gradient(circle at center 170px, transparent 85px, white 70px), radial-gradient(circle at 170px center, transparent 85px, white 75px), linear-gradient(white, white);
background-size: 50%;
background-repeat: no-repeat;
background-position: right top, left bottom, left top;
}
<div class="heart2"></div>
your css should be
.heart-img{
position:absolute;
width:40px;
height:40px;
top:20px;
left:30px;
z-index:1000;
}
html
<div class="heart">
<img src="http://lorempixel.com/400/200/sports/1" class="heart-img">
</div>
https://jsfiddle.net/9g1qswdd/3/
If you want to add a dynamic image inside of the heart something like this should do the trick:
https://jsfiddle.net/kn1m081z/
I've added some simple CSS to set the size of the image like this:
.heart img
{
position:relative;
z-index:3;
left:34px;
top:20px;
width:30px;
height:30px;
background:#ff5500
}
I've given the image a background colour so you can see where the image is - once you dynamically add an image src to the image tag I have added you will see the dynamic image inside of the heart - this should be what you're after!
You can add background image on .heart and shift 5px bottom to the heart
.heart {
background-image: url('');
}
.heart:before,
.heart:after {
top: 5px;
}
I would suggest to make use of clip-path property of CSS. I tried making a dialog box:
.clip-path {
clip-path: polygon(5% 5%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
}
https://jsfiddle.net/9g1qswdd/5/
similarly you can try making a heart with clip-path property. To make life easier, you can use this tool to do that for you: http://bennettfeely.com/clippy/
you have to make img class "relative" and heart class "absolute"
<style>
.img
{
position:relative;
background-image: url('');
}
.heart{position:absolute; top:50; left:50%;}
</style>
<div class="img"><div class="heart"></div></div>

Why background image with attachment:fixed and transform:scale moves on scroll?

Background acts as expected without transform:scale
after adding transform:scale value unwanted parallax effect appears: http://codepen.io/fekla/pen/VmqPZa (scroll down).
<div class="holder">
<div class="image"></div>
</div>
html,body {
margin:0px;
padding:0px;
height:100%;
width:100%;
}
.holder {
width:100%;
height:100%;
background-color:black;
overflow: hidden;
}
.image {
width:100%;
height:100vh;
background-image: url(http://lorempixel.com/output/nature-q-c-884-338-5.jpg);
background-attachment: fixed;
background-size: cover;
background-position: center;
transform: scale(1.25);
}
seems to be a known Webkit bug:
https://bugs.chromium.org/p/chromium/issues/detail?id=20574
P.S. also there seems to be little interest in actually fixing it

repeat-y left 50px repeats image on top as well

I have the following rule:
background: url(../img/redlines.png) repeat-y left 50px;
As you can see, the background image should start 50px below its div, and it works with no-repeat, but if I set repeat-y part of the image shows up at top of the div as well.
Any way to avoid this, and to keep repeating downwards only?
This is how it's supposed to function. For a tiled image, the position is merely the starting position. I would suggest something like:
HTML
<div class="foo">
<div class="bar">
<div class="content">
</div>
</div>
</div>
CSS
.foo {
padding-top: 50px;
}
.bar
background: url(../img/redlines.png) repeat-y left top;
}
.content {
margin-top: -50px;
}
When you use repeat-y, adding 50px to the top only changes the floating point of where the repeat starts.
You will need to add margin or relative/absolute positioning to achieve the same effect.
as you haven't provided a jsfiddle or any images, i'm assuming you could try background-position attribute in css.
refer to: http://www.w3schools.com/cssref/pr_background-position.asp
you may try :after on your container, see this example:jsfiddle
<div id="test"></div>
#test {
width: 500px;
height: 500px;
position:relative;
}
#test:after {
content:"";
position:absolute;
top:50px;
left:0;
right:0;
bottom:0;
background: url(http://www.gettyimages.co.uk/CMS/StaticContent/1391099215267_hero2.jpg) repeat-y left;
}

CSS opacity within an image

What's the best way (if any) to make the inside box transparent so the image can be seen with no opacity (clear image) and the rest of the outer box opaque. So far this is what I'm doing:
<style>
#a {
background-color: black;
float: left;
} #b {
opacity : 0.4;
filter: alpha(opacity=40);
} #div {
position: absolute;
height: 30px;
width: 30px;
top: 90px;
left: 90px;
border: 1px solid #FFF;
background: transparent;
}
</style>
<div id="a">
<div id="b">
<img src="http://clagnut.com/images/ithaka.jpg" />
</div>
</div>
<div id="div"></div>
Any ideas? thx
The maximum opacity of an element is the opacity of its parent element. So if div#b has an opacity of 40%, if his children have 100% opacity in style they will also be 40% absolute opacity.
To accomplish what you're describing (at least what I think you're describing), one way could be to have both the transparent wrapper and the image children of a parent div with relative positioning. You can absolutely position both of the children inside of that wrapper so that the image shows up on top of the transparent box.
Edit: Here is the code for the effect you are describing. My example has a 480 x 320 image, and a 30-pixel border:
<style>
#back {background-image:url(mypicture.jpg);
width:480px;
height:320px;
position:relative;}
#middle {position:absolute;
width:480px;
height:320px;
background-color:#000;
opacity:0.4;
filter:alpha(opacity=40);
top:0;
left:0;}
#front {position:absolute;
width:420px; /* 30px border on left & right */
height:260px; /* 30px border on top & bottom */
background-image:url(mypicture.jpg);
background-position:-30px -30px; /* compensate for the border */
top:30px;
left:30px;}
</style>
<div id="back">
<div id="middle">
</div>
<div id="front">
</div>
</div>
If I understand you correctly, try using just one div (i.e. get rid of the outer one with ID "a") and setting a colored border around it. Or you could get more flexibility by "faking" a border using 4 divs for the left, right, top, and bottom edges and 4 more for the corners.
It's kind of hard to know what you mean without an example page, or screenshots of what you expect and what you're actually getting.
EDIT: I was about to edit in basically the same thing Rex M wrote. Here's another (although idealistically inferior) way to do it:
<style>
#a {
float: left;
position: relative;
}
div.overlay {
opacity: 0.4;
background-color: black;
position: absolute;
}
#t {
left: 0; top: 0; height: 90px; width: 450px;
}
#b {
left: 0; top: 120px; height: 218px; width: 450px;
}
#l {
left: 0; top: 90px; height: 30px; width: 90px;
}
#r {
left: 120px; top: 90px; height: 30px; width: 330px;
}
</style>
<div id="a">
<div id="t" class="overlay"></div>
<div id="b" class="overlay"></div>
<div id="l" class="overlay"></div>
<div id="r" class="overlay"></div>
<img src="http://clagnut.com/images/ithaka.jpg">
</div>
If you want to be sure that the images have a certain color for a background, you could just as well stick a background to all IMG-elements in your stylesheet:
div#a img { background: #FFF; }
Anyhow, the filter-property in CSS should not be relied upon, as it is not part of the official specifications for CSS 2.1.
I might have misunderstood the question, though. Could you rephrase it or provide pictures of expected results?
To follow on what Rex M said, you'll need to change things so that the non-transparent elements aren't children of the transparent elements.
You can use absolute or relative positioning to line up your "border" with the picture, although this can often have inconsistencies between browsers.
The most painless way off the top of my head is to use javascript to get the top and left pixel locations of the image and set the top/left css properties of the border to match (and set the size of the border to that of the image).
UPDATE:
The asker showed an example of what he is trying to recreate. In the example linked, the shaded areas (the "not selected" area) of the picture is created by 4 divs.
The top and bottom divs are the full width of the image, and are set to have a height that is the difference between the top/bottom of the selection box and the top/bottom of the image respectively.
The side divs have height and width modified so that they fill in the "side areas" of the image.
The sizes are updated via a mousemove event.

Resources