linear-gradient rendering issue firefox - html

I'm trying to draw several grids of various sizes but I'm having an issue with Firefox - linear-gradient is breaking up for me in many places.
It's working all fine on Google Chrome with any units provided (px/mm/%/rounded/float) but it's doing some funny stuff on Firefox. I've tried using different units/rounding/prefixed/3d hacks but none of this is working.
div {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-image: linear-gradient(to right, black 1px, transparent 1px),
linear-gradient(to bottom, black 1px, transparent 1px);
background-size: 5mm 5mm;
}
<div></div>

A repeating gradient should give better result but it's always tricky when it comes to small values like 1px with gradients
div {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background-image:
repeating-linear-gradient(to right, black 0 1px, transparent 0 5mm),
repeating-linear-gradient(to bottom, black 0 1px, transparent 0 5mm);
}
<div></div>
you can also consider an SVG here (adjust the viewBox, width and height or the rect until you get a good result)
div {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
background:
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='black'> <rect x='0' y='0' width='1' height='100%' /> <rect x='0' y='0' width='100%' height='1'/></svg>")
0 0/5mm 5mm;
}
<div></div>
Also like below with only SVG:
svg {
position:absolute;
top:0;
left:0;
width:100%;
height:100%;
}
<svg xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
<rect x='0' y='0' width='1' height='100%' />
<rect x='0' y='0' width='100%' height='1'/>
</pattern>
</defs>
<rect width="3000" height="3000" fill="url(#grid)" />
</svg>

Related

Creating a Diagonal Mask Effect

I'm wondering how I would go about creating a diagonal mask like effect. The mask would show all in the top left corner, hide the middle part, then show all in the bottom right corner. In the example, the mask would be on the .container element and mask out any children in the div as well.
I've looked at resources online, specifically here, and can't get this effect to work on non-image elements. Is there a different type of property to use in CSS to achieve this effect? I was thinking maybe SVG, but I'd like it to adapt to the width and height of the element, and wasn't sure how to pull that off.
JS Fiddle
.container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
mask: gradient(linear, left top, right bottom,
color-stop(0.00, rgba(0,0,0,1)),
color-stop(0.35, rgba(0,0,0,1)),
color-stop(0.50, rgba(0,0,0,0)),
color-stop(0.65, rgba(0,0,0,1)),
color-stop(1.00, rgba(0,0,0,1)));
}
.shape {
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
background: red;
}
<div class="container">
<div class="shape"></div>
</div>
The mask would look something like this image.
Maybe so?
.container {
width:50%;
height:50%;
}
.rect1 {
fill: url('#grad1');
}
<div class="container">
<svg class="the-svg" viewBox="0 0 200 200" >
<defs>
<linearGradient id="grad1" x1="0" x2="1.0" y1="0" y2="1.0" >
<stop offset="0%" stop-color= "white"/>
<stop offset="35%" stop-color="white"/>
<stop offset="50%" stop-color="black"/>
<stop offset="65%" stop-color="white"/>
<stop offset="100%" stop-color="white"/>
</linearGradient>
</defs>
<rect class="rect1" x="0" y="0" width="100%" height="100%" />
</svg>
</div>
The solution is adaptive and works in all browsers, including Edge
Using mask-image works here. Updated JSFiddle.
.container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
-webkit-mask-image: linear-gradient(-45deg, black 0%, transparent 35% , transparent 50%, transparent 65%, black 100%);
mask-image: linear-gradient(-45deg, black 0%, transparent 35% , transparent 50%, transparent 65%, black 100%);
}

Creating a background-image gradient triangle that is horizontally centered

I want to create a triangle pointing down in css by using clip-path: polygon(...) and apply a gradient on it using background-image: linear-gradient(...).
This all works fine but I need this shape as the background of my web page.
It needs to always be centered and it needs to clip/cut off the left and right edges that do not fit in the browser window. The triangle should not re-scale itself; I want to preserve the steepness of the triangle's edges and the height of the triangle should not change:
As illustrated, the triangle should stay the same width and height even when the browser window is too small to contain it.
So far I have:
div.main-background {
position: absolute;
z-index: -1;
top: 0;
height: 500px;
width: 100%;
background-image: linear-gradient(to bottom, #65AAB0, #AEE2B6);
background-attachment: fixed;
background-position-x: center;
background-size: 1400px 500px;
clip-path: polygon(50% 80%, 0 0, 1400px 0);
}
<div class="main-background"></div>
but this is clearly wrong.
You can do this with SVG
html,
body {
margin: 0
}
svg {
width: 100%;
}
<svg viewBox="0 0 1920 400" height="400" preserveAspectRatio="xMidYMax slice">
<defs>
<linearGradient id="Gradient1" x1="0" x2="0" y1="0" y2="1">
<stop offset="0%" stop-color="#65AAB0"></stop>
<stop offset="100%" stop-color="#AEE2B6"></stop>
</linearGradient>
</defs>
<polygon points="0,0 960,400 1920,0" fill="url(#Gradient1)"></polygon>
</svg>
Using viewport units, is this what you want? Works on any resolution.
div.main-background {
position: absolute;
z-index: -1;
top: 0;
left: 0;
right: 0;
height: 35.71vw;
background-image: linear-gradient(to bottom, #65AAB0, #AEE2B6);
background-attachment: fixed;
background-position: center;
clip-path: polygon(50% 80%, 0 0, 100vw 0);
}
<div class="main-background"></div>
You can try multiple background like below. I made the triangle to have a width of 600px and a height of 300pxthat you can easily adjust.
body {
background:
linear-gradient(to bottom right,transparent 49.8%,#fff 50%) calc(50% + 150px) 0 /300px 300px,
linear-gradient(to bottom left, transparent 49.8%,#fff 50%) calc(50% - 150px) 0 /300px 300px,
linear-gradient(to bottom, #65AAB0, #AEE2B6)top center/ 600px 300px;
background-repeat:no-repeat;
}
Easier with CSS variable :
body {
--w:800px;
--h:300px;
background:
linear-gradient(to bottom right,transparent 49.8%,#fff 50%) calc(50% + calc(var(--w)/4)) 0 /calc(var(--w)/2) var(--h),
linear-gradient(to bottom left, transparent 49.8%,#fff 50%) calc(50% - calc(var(--w)/4)) 0 /calc(var(--w)/2) var(--h),
linear-gradient(to bottom, #65AAB0, #AEE2B6)top center/ var(--w) var(--h);
background-repeat:no-repeat;
}
You are going about it the wrong way. Your div contains no content and is thus simply decorative cruft. If you want a page background of certain appearance, then whatever appearance the background should have, goes into the background property of the document element (typically body, or html).
Get rid of your useless div.main-background which serves no purpose whatsoever, and use the following background image, either standalone (in its own SVG file) or inline using a data: URI:
<?xml version="1.0" ?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1">
<polygon fill="lime" points="0,0 0.5,0.4 1,0" />
</svg>
The following CSS declaration will use the above as a background image, from your explanation the background size should be a definite length (as opposed to one relative to viewport dimensions), I will use 40em because I didn't pick any clues from your question:
body {
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1 1"><polygon fill="lime" points="0,0 0.5,0.4 1,0" /></svg>');
background-size: 40em;
background-repeat: no-repeat;
background-position: top center;
}
Alternatively, you can use a standalone SVG file, then your background rule will be different:
background: url(<URL-of-SVG-file>);
You can add the gradient easily by editing SVG content, it's a basic SVG feature, one of the other answers here even demonstrates how.
Maybe you can use that kind of trick with just CSS and an after pseudo-element:
body {
overflow: hidden;
}
.arrow-down {
--w:800px;
--h:300px;
position: relative;
width: var(--w);
height: var(--h);
margin-left: 50%;
transform: translate(-50%, 0);
background-image: linear-gradient(to bottom, #65AAB0, #AEE2B6);
}
.arrow-down::after{
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
border: solid white;
border-width: calc(var(--h)/2) calc(var(--w)/2);
border-top-color: transparent;
}
<body>
<div class="arrow-down"></div>
</body>
Of course, you can tweak width and height to better suit your needs.

How to get an SVG to have a fluid width without changing its height?

I would like to accomplish two things:
The SVG width scales dynamically to take up 100% of the container's width.
SVG's is either stretched or smushed when the container's width changes (meaning the wave drawn with the svg's path)
SVG's height remains fixed to 760px. Currently if you resize the container, the SVG's height is reduced which is not desired.
.container {
width: 100%;
background: green;
height: 760px;
}
svg {
width: 100%;
}
svg path {
width: 100%;
}
<div class="container">
<svg width="1440" height="760" viewBox="0 0 1440 760" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M677.112 54.1657C400.36 -43.9336 110.391 13.291 0 54.1657V760H1440V54.1657C1301.02 95.0404 953.865 152.265 677.112 54.1657Z"
fill="purple"
/>
</svg>
</div>
I would probably use the SVG as background of a div and you can make the height of the div fixed and adjust the background-position to be top
.container {
width: 100%;
background: green;
height: 760px;
}
.container>div {
height: 100%;
background:
url('data:image/svg+xml;utf8,<svg width="1440" height="760" viewBox="0 0 1440 760" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M677.112 54.1657C400.36 -43.9336 110.391 13.291 0 54.1657V760H1440V54.1657C1301.02 95.0404 953.865 152.265 677.112 54.1657Z" fill="purple"/></svg>') top/100% no-repeat,
/*cover the bottom part with the same color*/
linear-gradient(purple, purple) bottom/ 100% calc(100% - 20vw) no-repeat;
}
<div class="container">
<div>
</div>
</div>
You can also reduce the code to keep only the container:
.container {
height: 760px;
background:
url('data:image/svg+xml;utf8,<svg width="1440" height="760" viewBox="0 0 1440 760" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M677.112 54.1657C400.36 -43.9336 110.391 13.291 0 54.1657V760H1440V54.1657C1301.02 95.0404 953.865 152.265 677.112 54.1657Z" fill="purple"/></svg>') top/100% no-repeat,
/*cover the bottom part with the same color*/
linear-gradient(purple, purple) bottom/ 100% calc(100% - 20vw) no-repeat,
green;
}
<div class="container">
</div>
You can try adding preserveAspectRatio="none" to the svg tag. This does seem to mess with the position a bit but might be a good start.
.container {
width: 100%;
background: green;
height: 760px;
}
svg {
width: 100%;
}
svg path {
width: 100%;
}
<div class="container">
<svg width="1440" height="760" viewBox="0 0 1440 760" fill="none" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M677.112 54.1657C400.36 -43.9336 110.391 13.291 0 54.1657V760H1440V54.1657C1301.02 95.0404 953.865 152.265 677.112 54.1657Z"
fill="purple"
/>
</svg>
</div>

How to create a polygon shape div

I would like to create HTML element like on image here:
A problem is the DIV element has polygon shape instead of regular rectangle, will be placed above other elements as something like popup and inside that element there is necessary to show an image with rectangular shape in source but showed on web like filling all space included triangle on the left side.
Do you think is there any possibility to realize that without preparing showed images as transparent PNGs in proper polygon format? Only by CSS3 transform or use canvas or SVG?
One method could be to split the image into two containers which are 50% the size of the parent, transform each of them separately and position the backgrounds to look like they are one single image. The transform could either be a skew (used in the answer) or a perspective based rotation.
Note that since we are transforming the container, we have to apply the reverse effect to the actual image for it to look normal.
.image {
position: relative;
height: 150px;
width: 450px;
overflow: hidden;
}
.top-container,
.bottom-container {
position: absolute;
left: 0px;
height: 50%;
width: 100%;
overflow: hidden;
backface-visibility: hidden;
}
.top-container {
top: 0px;
transform-origin: right bottom;
transform: skew(-20deg);
}
.bottom-container {
bottom: 0px;
transform-origin: right top;
transform: skew(20deg);
background-position: 0% 100%;
}
.top-container:after,
.bottom-container:after {
position: absolute;
content: '';
height: 100%;
width: 100%;
left: -14px; /* tan(20) * (height/2) / 2 */
background: url(http://lorempixel.com/450/150);
background-size: 100% 200%;
}
.top-container:after {
top: 0px;
transform: skew(20deg);
}
.bottom-container:after {
bottom: 0px;
transform: skew(-20deg);
background-position: 0% 100%;
}
/* Just for demo */
body {
background: linear-gradient(90deg, crimson, indianred, purple);
}
.image2 {
margin-top: 10px;
height: 150px;
width: 450px;
background: url(http://lorempixel.com/450/150);
}
<div class="image">
<div class='top-container'></div>
<div class='bottom-container'></div>
</div>
<!-- this is the actual image for comparison -->
<h3>Original Image</h3>
<div class='image2'></div>
I was about to suggest usage of SVG and clipPath but since Persijn has already posted that sample, I have added below a different version with polygon.
.vector {
position: relative;
height: 150px;
width: 450px;
}
svg {
position: absolute;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
}
polygon {
fill: url(#image);
}
/* Just for demo */
body {
background: linear-gradient(90deg, crimson, indianred, purple);
}
<div class='vector'>
<svg viewBox='0 0 450 150' preserveAspectRatio='none'>
<defs>
<pattern id='image' height='150' width='450' patternUnits='userSpaceOnUse'>
<image xlink:href='http://lorempixel.com/450/150' height='150' width='450' />
</pattern>
</defs>
<polygon points='15,0 450,0 450,150 15,150 0,75' />
</svg>
</div>
SVG
Fiddle example
Solution found by Jbutler438
using a clip-path and image tag in svg you can easily cut out an arrow shape at the front.
<?xml version="1.0" ?>
<svg width="300px" height="300px" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<clipPath id="myClip">
<path d="M30 0, 100 0, 100 100, 30 100 0,50Z" />
</clipPath>
</defs>
<image xlink:href="http://lorempixel.com/300/300" x="0" y="0" width="100%" height="100%" clip-path="url(#myClip)" />
</svg>

Circular hole in a <div> [duplicate]

This question already has answers here:
Transparent hollow or cut out circle
(7 answers)
Closed 8 years ago.
I am looking for a way to create a square div of relative size, say, 70% x 70% with a background color and a circular hole in it (so that the background can be seen behind it) of the same size so that the sides of the div are tangent.
You could use radial-gradient to achieve this.
html,
body {
height: 100%;
margin: 0;
background: url(http://www.lorempixel.com/600/400) 100% 100%;
}
div {
position: relative;
width: 70%;
height: 70%;
background: -webkit-radial-gradient(50% 50%, circle, transparent 10%, #000 10%);
background: -moz-radial-gradient(50% 50%, circle, transparent 10%, #000 10%);
background: radial-gradient(50% 50%, circle, transparent 10%, #000 10%);
margin: 0 auto;
}
<div></div>
Here's an svg approach.
body {
background: url(http://www.lorempixel.com/600/400/);
background-size: 100% 100%;
margin: 0;
}
<svg viewBox="0 0 400 200" width="400" height="200">
<path d="M0,0 L400,0 L400,200 L0,200z M200,100 m-50,0 a50,50 0 1,0 100,0 a50,50 0 1,0 -100,0z" fill="black" />
</svg>