How could I achieve a background that looked similar to this image:
Only 3 colors, angled from the top corner out like a sunray.
Maybe sticking with a simple PNG or SVG background image would be a better approach.
The effect can be achieved with CSS using pseudo-elements and transforms and the below is a sample snippet. But I don't think using CSS is the correct option for this. It would be better to use a PNG image.
The snippet uses a couple of pseudo-elements with different background colors skewed at required angles to produce the three-color effect.
.bg {
position: relative;
height: 200px;
width: 400px;
padding: 4px;
background: orange;
overflow: hidden;
}
.bg:after,
.bg:before {
position: absolute;
content: '';
left: 0px;
height: 100%;
width: 100%;
transform-origin: right top;
}
.bg:before {
top: 0px;
background: red;
transform: skewY(-45deg);
}
.bg:after {
top: -100%;
background: yellow;
transform: skewY(-15deg);
}
span {
position: relative;
z-index: 2;
}
/* Just for demo */
.bg:hover {
height: 200px;
width: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="bg">
<span>Some content inside</span>
</div>
Angled linear-gradients also could be used but I don't think they are good for dynamic sized container elements as the angles need to be modified as the dimensions change to keep the appearance the same.
Below is a snippet using linear-gradient. Hover on the shape to see how a change of width and/or height affects it.
.bg {
position: relative;
height: 200px;
width: 400px;
background: linear-gradient(310deg, red 30%, transparent 30%), linear-gradient(340deg, transparent 58%, yellow 58%), orange;
overflow: hidden;
}
.bg:hover {
height: 200px;
width: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script>
<div class="bg">
<span>Some content inside</span>
</div>
SVG
This can be done with SVG.
I used three polygon shapes. This can be set to a background-image.
Or alternatively can be used inline so you can use css properties on it.
html, body {
margin: 0;
padding: 0;
}
.triple {
width: 250px;
height: 250px;
}
.triple:hover {
width: 500px;
height: 100px;
}
<svg class="triple" viewBox="0 0 100 100" preserveAspectRatio="none">
<polygon fill="#dd2" points="0,0 100,0 0,60" />
<polygon fill="#bb2" points="0,60 100,0 30,100 0,100 " />
<polygon fill="#992" points="30,100 100,0 100,100" />
</svg>
Yes, it can be done with gradients, in a responsive way.
That is asuming that when the aspect ratio changes, you don't want to keep the angles, but the relative positions
The trick is to use simbolic names in the gradient direction, and then playing with the size and the position of the background-image
.test {
display: inline-block;
border: solid 1px black;
background-image: linear-gradient(to top left, tomato 50%, transparent 50%),
linear-gradient(to bottom right, lightgreen 50%, transparent 50%);
background-size: 60% 100%, 100% 50%;
background-repeat: no-repeat;
background-position: bottom right, top left;
}
#test1 {
width: 200px;
height: 100px;
}
#test2 {
width: 100px;
height: 100px;
}
#test3 {
width: 70px;
height: 100px;
}
<div class="test" id="test1"></div>
<div class="test" id="test2"></div>
<div class="test" id="test3"></div>
Use a 4-color GIF image. This will give you both cross-browser/platform compatibility as well as backward compatibility, and the size will be small with this type of image. If the colors are subtle as shown the "jaggies" will be camouflaged somewhat (or provide a larger size).
A good option is to use SVG which has good support in modern up-to-date browsers.
Related
The image below is what I am intending to do:
Here is my situation right now:
My problem is I am not quite sure what to do with the z-index in order to have the image go inside the background but still over it.
Classes:
<img class="background" src="">
<img class="bubble_img" src="">
CSS:
.background {
width: 100%;
height: 100%;
position: relative;
z-index: 2;
display: block;
}
.bubble_img {
bottom: 0;
max-height: 110%;
position: absolute;
right: 0;
transition: all 1s;
z-index: 1;
}
If I switch the z-index around (2 and 1) the image of the person just goes on the and it goes over the background borders:
Would appreciate any help, thank you.
Instead of using the yellow background as an image, you can make it as a div element with a border-radius. Then add a overflow: hidden to partly hide the image:
div {
width: 300px;
height: 300px;
border-radius: 20% 45% 45% 5%;
background: #f5e511;
overflow: hidden;
}
div img {
max-width: 100%;
max-height: 100%;
}
<div>
<img src="https://www.pngkey.com/png/full/889-8891004_calling-girl-png-call-center-girl-png.png" />
</div>
That can be done with the CSS mask, as in the example below (the mask image here is base64 encoded because of CORS issues when using i.stack.imgur.com):
.background {
width: 100vw;
height: 100vh;
background: url(https://i.stack.imgur.com/WI6mO.png) #FE0 no-repeat;
mask: var(--mask);
-webkit-mask: var(--mask);
--mask: no-repeat url(data:image/png;base64,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);
}
<div class="background"></div>
I want to get the result below but without using the at syntax because it's not supported in Safari, I'm having a hard time with it. Does any one know any approach? Thank you in advance!
#content {
background-color: black;
height: 300px;
width: 500px;
}
#inverted-circle {
background: radial-gradient(110% 200% at 50% 0, white 49.9%, rgba(255,255,255,0) 50.05%);
position: relative;
content: '';
height: 220px;
width: 100%;
}
<div id="content">
<div id="inverted-circle"></div>
</div>
It's still not working on Safari on iOS
Consider background-size/background-position. You make the background twice bigger in height, you divide the vertical radius by 2 and you place your background at the bottom.
#content {
background-color: black;
height: 300px;
width: 500px;
}
#inverted-circle {
background:
radial-gradient(110% 100%, white 49.9%, transparent 50.05%)
bottom/
100% 200%;
height: 220px;
width: 100%;
}
<div id="content">
<div id="inverted-circle"></div>
</div>
Related to get more details: How to animate a radial-gradient using CSS?
You can also optimize your code with only one element:
#content {
height: 300px;
width: 500px;
background:
radial-gradient(55% 36.5%, white 99.5%, black 100%)
bottom /
100% 200%;
}
<div id="content">
</div>
I've tried the perspective solution here How to transform each side of a shape separately? but can't get it to work probably due to the irregularness of the shape. Only the top and right side columns are slanted, vertical and bottom are straight. How can I do this with CSS?
Using CSS borders you can create triangles and trapezoids.
You can achieve your shape joining a triangle and a trapezoid.
.triangle {
border: 0 solid red;
border-left-width: 500px;
border-top-width: 30px;
border-top-color: transparent;
}
.trapezoid {
border: 0 solid red;
width: 500px;
border-bottom-width: 150px;
border-right-width: 30px;
border-right-color: transparent;
}
<div class="triangle"></div>
<div class="trapezoid"></div>
Method 1: Clip path
You could make use of CSS clip-path feature to clip a rectangle into the required polygon shape.
div {
box-sizing: border-box;
height: 150px;
width: 250px;
background: red;
padding: 10px;
-webkit-clip-path: polygon(0% 0%, 90% 10%, 100% 100%, 0% 100%);
clip-path: polygon(0% 0%, 90% 10%, 100% 100%, 0% 100%);
}
div#image {
background: url(http://lorempixel.com/400/200);
}
/* Just for demo */
div{
float: left;
margin: 10px;
transition: all 1s;
}
div:hover{
height: 200px;
width: 300px;
}
<div>Some text</div>
<div id="image"></div>
Pros:
Supports non-solid color fills inside the shape and also allow text to be present inside.
The shape is responsive and can adapt even if the container's dimensions change.
Cons:
Poor browser support for the CSS clip-path feature. This can be overcome by using inline SVG for the clip-path like in the below snippet as this has much better browser support.
div {
box-sizing: border-box;
height: 150px;
width: 250px;
padding: 10px;
background: red;
-webkit-clip-path: url(#clip);
clip-path: url(#clip);
}
div#image {
background: url(http://lorempixel.com/400/200);
}
/* Just for demo */
div{
float: left;
margin: 10px;
transition: all 1s;
}
div:hover{
height: 200px;
width: 300px;
}
<svg width="0" height="0">
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<path d="M0 0, 0.9 0.1, 1 1, 0 1z" />
</clipPath>
</defs>
</svg>
<div>
Some text
</div>
<div id="image"></div>
Method 2: CSS Transforms
Generally it is better not to use transforms when there is going to be content like image or text inside the shape (or) when the shape's background is not going to be a solid color because then we would either have to (a) reverse transform the child elements separately to make them look normal or (b) use absolute positioning.
For this particular shape, having text inside the shape is not a problem even while using transforms but having non solid background colors would be.
Option 1: Using two pseudo-elements
You could use a couple of pseudo-elements with skew transforms, position one on the top and the other on the right to produce the required shape. Hover the shape in snippet to see how it is created.
div {
position: relative;
height: 150px;
width: 250px;
background: red;
margin: 40px 40px 0px 0px;
}
div:after,
div:before {
position: absolute;
content: '';
background: red;
z-index: -1;
backface-visibility: hidden;
}
div:before {
height: 12.5%;
width: 100%;
top: 0px;
left: 0px;
transform-origin: right top;
transform: skewY(3deg);
}
div:after {
height: 100%;
width: 12.5%;
right: -1px;
top: -1px;
transform-origin: right top;
transform: skewX(10deg);
}
/* Just for demo */
div{
transition: all 1s;
}
div:hover{
height: 250px;
width: 300px;
}
div:hover:after{
background: blue;
}
div:hover:before{
background: green;
}
<div>Some text</div>
Pros:
Shape can be created with a single element and can have text inside it without any trouble.
Cons:
Having gradients (or) images as background for the shape is complex because they would need reverse rotation as mentioned earlier.
Shape is not 100% scalable as dimensions of the container should change proportionately for the shape to be maintained (hover on the shape in the snippet to see what I mean). Reason is same as mentioned here.
Option 2: Using one pseudo-element
This is pretty similar to the previous option except that this uses a single pseudo-element along with a overflow: hidden on the parent.
div {
position: relative;
box-sizing: border-box;
height: 200px;
width: 300px;
padding: 10px;
overflow: hidden;
}
div:after {
position: absolute;
content: '';
top: 0px;
left: -20px;
height: 100%;
width: 100%;
background: red;
transform-origin: left bottom;
transform: skewY(5deg) skewX(7.5deg);
z-index: -1;
}
div:hover {
height: 300px;
width: 500px;
transition: all 1s;
}
<div>Some text</div>
Pros:
Shape can be created with a single element and can have text inside it without any trouble.
Shape is responsive and can adapt even if the container's dimensions change .
Cons:
Same constraint as the previous option for gradient and image backgrounds.
Not suitable if the overflow: hidden on the parent is a constraint.
A solution is:
div {
width: 300px;
height: 100px;
margin:50px;
background-color: yellow;
border: 1px solid black;
}
.thisdiv {
-ms-transform: skewX(-20deg); /* IE 9 */
-webkit-transform: skewX(-20deg); /* Safari */
transform: skewX(-20deg); /* Standard syntax */
}
<div class="thisdiv">
This is the div I will skew
</div>
This is how to skew an element, if you want to make the shape you added, try using two overlaping div's, position, scale, rotate and skew, like this:
.outer-div{
position:relative;
margin:50px;
width:200px;
height:200px;
border:2px black dashed;
}
.inner-one{
position:absolute;
left:0;
bottom:0;
width:180px;
height:180px;
background:red;
}
.inner-two{
position:absolute;
bottom:2px;
right:0px;
width:200px;
height:195px;
background:red;
transform: rotate(7deg) skew(14deg) scale(0.905); /* Standard syntax */
}
<div class="outer-div">
<div class="inner-one">
</div>
<div class="inner-two">
</div>
</div>
2 Triangle Solution for Irregular Quadrilateral in CSS
In looking at your image, I notice that the skew at the top and right are really just long, narrow triangles overlaying the rectangle.
So what I did was create triangles using CSS border properties and absolutely position them over the rectangle.
#rectangle {
width: 400px;
height: 200px;
background-color: red;
margin-top: 25px;
position: relative;
}
#triangle-down {
border-left: 30px solid red;
border-right: 0;
border-top: 200px solid transparent;
position: absolute;
right: -30px;
top: 0;
}
#triangle-left {
border-top: 0;
border-bottom: 15px solid red;
border-right: 400px solid transparent;
position: absolute;
right: 0;
top: -15px;
}
<div id="rectangle">
<div id="triangle-down"></div>
<div id="triangle-left"></div>
</div>
jsFiddle demo
You could check out the clip-path property (see below from MDN), but support is very patchy. Chrome 24+ supports with prefix and FF, but only URL values, which reference a path in an SVG. You can read more about clip-path here.
Here's a basic pen - this will only work in Chrome.
From MDN
The clip-path CSS property prevents a portion of an element from getting displayed by defining a clipping region to be displayed i.e, only a specific region of the element is displayed. The clipping region is a path specified as a URL referencing an inline or external SVG, or shape method such as circle(). The clip-path property replaces the now deprecated clip property.
developer.mozilla.org/en-US/docs/Web/CSS/clip-path (sorry, not enough rep to link)
I'm looking for a way to create bent top and bottom borders like the div in this image. I've tried some ways mentioned here but it depends on using white divs with border-radius on top of the main div but as you can see in this image it should be transparent to display the background image.
This is possible using svg.
For responsiveness remove the svg's width and height attributes, add viewBox="0 0 400 150" then try changing #image's width and height, the svg will respond to its width and height.
Demo on Fiddle demonstrating responsive shape.
Browser support for this approach - This will work on all browsers but IE8.
body {
background: teal;
}
#image {
width: 600px;
height: 300px;
position: relative;
background: url(http://lorempixel.com/600/300);
}
svg {
position: relative;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
<div id="image">
<svg width="400" height="150">
<path opacity="0.6" fill="red" d="M0,10 Q0,0 10,0 Q195,40 390,0 Q400,0 400,10 Q390,75 400,140 Q400,150 390,150 Q195,100 10,150 Q0,150 0,140 Q10,75 0,10" />
</svg>
</div>
Another posibility, not using clipping but multiple backgrounds.
Technically less advanced than chipChocolate answer, just providing an alternative
.test {
position: absolute;
left: 50px;
top: 50px;
width: 400px;
height: 100px;
border-radius: 10px;
background-image: radial-gradient(circle at center -778px,
transparent 800px, rgba(255,0,0,0.4) 800px),
radial-gradient(circle at center 828px,
transparent 800px, rgba(255,0,0,0.4) 800px);
background-position: center top, center bottom;
background-size: 100% 50%, 100% 50%;
background-repeat: no-repeat;
}
Thw idea is to divide the element in 2 halves, and then set in each a radial gradient that matches the corners position. The final posiotion of the gradients adjusted by hand.
Can de done responsively also.
demo
body {
width: 100%;
height: 100%;
background: url(http://placekitten.com/g/600/300);
}
.test {
position: absolute;
left: 50px;
top: 50px;
width: 400px;
height: 100px;
border-radius: 10px;
background-image: radial-gradient(circle at center -778px,
transparent 800px, rgba(255,0,0,0.4) 801px),
radial-gradient(circle at center 828px,
transparent 800px, rgba(255,0,0,0.4) 801px);
background-position: center top, center bottom;
background-size: 100% 50%, 100% 50%;
background-repeat: no-repeat;
}
<div class="test"></div>
An other approach with one div, 2 pseudo elements , border-radius and box-shadows :
div {
width: 70%; height: 150px;
margin: 20px auto;
position: relative;
border-radius: 10px;
overflow: hidden;
opacity: 0.5;
}
div:before,div:after {
content: '';
position: absolute;
height: 100%; width: 300%;
left: -100%;
border-radius: 100%;
box-shadow: 0px 0px 0px 140px red;
}
div:before {top: -146px;}
div:after {bottom: -146px;}
body {background: url('http://lorempixel.com/output/people-q-c-640-480-1.jpg');background-size: cover;}
<div></div>
Actually doing this using the CSS would almost be impossible, and you would be good if you just try out a simple PNG image, created using Photoshop, Google Images etc, and create the image exactly of this size and then use it inside the website.
You can add the transparency to the image while creating it by using the Adobe UI tools for editing the image, or you can use the alpha filter in CSS to set the transparency effect to it to display the element that is residing behind it (the effect that you want).
Lets assume I have a div with a Gradient applied as a background-property.
I now want to overlay a black PNG (of smaller size) and set the PNG to have a background-blend-mode of overlay. Unfortunately I have no idea on how to achieve this.
I know I can have a working background-blend-mode when I render the Gradient into the CSS of the Div with the PNG image like:
background: url(../img/plus.png), linear-gradient(to bottom, #24cae4 0%, #1f81e3 100%);
background-blend-mode: overlay;
This however results in the Gradient being as small as the actual PNG, which is not a desired effect, like this:
What I want to achieve is this with pure CSS (if possible):
Here a Codepen to illustrate what I'm trying to do: http://codepen.io/anon/pen/zxOXGP
Notice the Black Icon. I wanna overlay this.
Try using mix-blend-mode instead of background-blend-mode and switch to simple text for the plus-sign or a webfont for more custom figures.
Example Codepen of the below:
.placeholder {
position: relative;
width: 400px;
height: 300px;
background-image: -moz-linear-gradient(#ff0000, #0000ff);
background-image: -webkit-linear-gradient(#ff0000, #0000ff);
background-image: linear-gradient(#ff0000, #0000ff);
}
.center {
position: absolute;
top: 25%;
width: 100%;
font-size: 120px;
}
.center span {
display: block;
text-align: center;
color: red;
mix-blend-mode: screen;
}
<div class="placeholder">
<div class="center"><span>+</span>
</div>
</div>
The gradient sandwich
Ingredients
The :before forms the bottom z-layer with z-index: 1, it is full opacity
The .content div forms the filling, central z-layer, with z-index: 2. It needs position: relative to take its z-index.
The :after forms the top z-layer with z-index: 3 and completes our lunch item. It is half opacity.
This is the tasty result:
Full Example
I have removed all but the standard CSS3 gradient for simplicity. View in a supporting browser.
.gradient {
position: relative;
height: 200px;
padding: 20px;
}
.gradient:before,
.gradient:after {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
content: '';
display: block;
background-size: 100%;
background-image: linear-gradient(to bottom, #24cae4 0%, #1f81e3 100%);
opacity: 0.5;
}
.gradient:before {
opacity: 1;
z-index: 1;
}
.gradient:after {
z-index: 3;
}
.overlayed_image {
position: relative;
width: 64px;
height: 64px;
display: block;
margin: auto;
background-size: contain;
background-repeat: no-repeat;
background-position: 50% 50%;
background-image: url(http://cdn.flaticon.com/png/256/9029.png);
}
.content {
position: relative;
z-index: 2;
}
<div class="gradient">
<div class="content">
You can see me!
<div class="overlayed_image"></div>
</div>
</div>