I am struggling to create the above design of the green background, two white triangles and blue dots on the point of the triangles.
I have to create two triangles using W3School tutorial but they are not responsive causing issues. I have created the green background in PS with white triangles and blue dots but cannot get the image to sit in the same position across screen sizes.
Any help in creating the above using HTML/CSS would be great.
You can use clip-path on a pseudo element to create the graph-like zig zag and background images on another pseudo element to place the blue dots.
It is important to note that everything has to be done in relative terms, e.g. %s, so that the whole is responsive.
While this is pretty straightforward for the zig zag, adjustments have to be made to the placing of the dots as things are placed relative to their top left corner not relative to their center, which is what we require for the circles.
Also the height of the 'background' (the zigzag plus a little bit below the green to accomodate the circle at the bottom) has to be specified in terms of the width. Eventually CSS aspect-ratio will be useful for this but just at the moment not all browsers support it so this snippet uses the well-known hack of defining an element's height in terms of padding (the units for which are always the width's).
* {
padding: 0;
margin: 0;
}
.graphbg {
background: white;
width: 100vw;
height: 100vh;
position: relative;
margin: 0;
padding: 0;
}
.graphbg::before,
.graphbg::after {
margin: 0;
padding: 0;
box-sizing: border-box;
overflow: hidden;
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 1;
overflow: hidden;
--w: 4;
/* set these so --w/--h is the proportion of width to height you want this background to have */
--h: 1;
/* soon you will be able to use aspect-ratio: 4 / 1 but currently, August 2021, Safari IOS does not support it */
height: 0;
padding-top: calc( var(--h) / var(--w) * 100%);
/* to force the element to have the right height */
}
.graphbg::before {
background: green;
clip-path: polygon(0 0, 98% 0, 50% 95%, 25% 50%, 0 95%);
}
.graphbg::after {
background-image: radial-gradient(circle, blue 0 70%, transparent 70% 100%), radial-gradient(circle, blue 0 70%, transparent 70% 100%), radial-gradient(blue 0 70%, transparent 70% 100%), radial-gradient(blue 0 70%, transparent 70% 100%);
background-repeat: no-repeat;
background-size: 2% 8%;
background-position: -1% 99%, 24.5% 50%, 50% 97%, 99% -4%;
}
<div class="graphbg"></div>
Related
I'm trying to define a rotation of an element depending on viewport width in CSS.
Here with a "hard" "transform: rotate(-3.4deg);" :
https://i.postimg.cc/3NqY2Hzy/rotate-1.jpg
I'd like here more angle on smaller viewport width :
https://i.postimg.cc/SQHKX64g/rotate-2.jpg
I tried things like calc(12deg * 5vw) (and any other viewport's size variables units) but none seem compatible with an angle unit.
I could do it in javascript but I'm afraid it would show a bad glitch at page loading on slow computers / connections. I would like to avoid touching to top and bottom dividers, they are generated by a wordpress' theme.
Edit : The element I'm trying to dynamically rotate is the one containing the 3 texts.
If you forget angles but turn to using clip-path you can have a couple of pseudo elements on your element which have backgrounds one of darker and one of lighter green.
As the clip-paths are defined in terms of the percentage amounts rather than actual angles they automatically adjust to different viewports without the need for media queries:
div {
position: relative;
width: 100vw;
height: 30vw;
display: inline-block;
}
div::before,
div::after {
content: '';
position: absolute;
display: inline-block;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
div::before {
z-index: -2;
background-color: lightgreen;
clip-path: polygon(0 0, 100% 0%, 0 35%, 0 100%, 100% 70%, 100% 95%, 0 100%);
}
div::after {
z-index: -1;
background-color: green;
clip-path: polygon(0 0, 100% 0, 0 25%, 0 100%, 100% 75%, 100% 100%, 0 100%);
}
<div></div>
I'm looking to create this white arrow that goes inside the image with the HTML you can find in the snippet in a pure CSS way, not editing any HTML code.
.foto {
width: 100%;
float: left;
min-height: 215px;
background:
linear-gradient(to bottom right,transparent 50%,#fff 0) bottom right/10% 50% no-repeat, linear-gradient(to bottom left,#fff 50%,transparent 0%) top right/10% 50% no-repeat, url(https://s3.pagegear.co/1/contents/blog/2016/imagen_cachorro_comprimir.jpg) center/cover
}
<div class="foto bg_fix"><img src="https://s3.pagegear.co/1/contents/blog/2016/imagen_cachorro_comprimir.jpg" itemprop="image" width="724" height="230" style="display: none;"></div>
If you do not need to support Edge, you can get away with the clip-path. It's by far the easiest solution to your problem.
You can check the support on CanIUse
Also, amazingly helpful tool for this is Clippy, but don't forget to read about this technique on MDN - CSS clip-path.
.foto {
width: 100%;
float: left;
min-height: 215px;
-webkit-clip-path: polygon(100% 0%, 85% 50%, 100% 100%, 0 100%, 0% 50%, 0 0);
clip-path: polygon(100% 0%, 85% 50%, 100% 100%, 0 100%, 0% 50%, 0 0);
}
/* first value is X, and second value is Y coordinate. Feel free to experiment with percentages according to your needs. */
SOLUTION 2:
Old "trick" which has much much better support => CSS shapes.
You would basically need to create a new element (which is going to be your white triangle) and then put it on top of that image. Here's a sample code for a triangle that you need:
#triangle-left {
width: 0;
height: 0;
border-top: 50px solid transparent;
border-right: 100px solid red; /* red is just for display puproses */
border-bottom: 50px solid transparent;
}
<div id="triangle-left"><div>
Btw, you have both background-image and img tag in your html. Decide which one you want to use, and if you have problem with cropping the image, you may want to look into background position and/or object-fit.
You can correct you gradient like below. You were almost good, simply switch the position of both making the bottom one on the top and the top on on the bottom:
.foto {
min-height: 200px;
background:
linear-gradient(to bottom right,transparent 49.8%,#fff 50%) top right/10% 50%,
linear-gradient(to top right,transparent 49.8%,#fff 50%) bottom right/10% 50%,
url("https://s3.pagegear.co/1/contents/blog/2016/imagen_cachorro_comprimir.jpg") center/cover;
background-repeat:no-repeat;
}
<div class="foto bg_fix" ></div>
If I have this:
https://codepen.io/anon/pen/MveydB
body {
width: 100vh; height: 100vh;
background-image: radial-gradient(circle closest-side, #00bffb, rgba(0, 0, 0, 1));
}
How I can have something like this instead?:
It's impossible to edit HTML in this case too, because it's a theme for Linux.
Cover with a linear gradient
Paint a half transparent, half black linear gradient on top of it.
.bg {
width: 100vh;
height: 100vh;
background: linear-gradient(to bottom, transparent 50%, black 50%),
radial-gradient(circle closest-side, #00bffb, black);
}
body {
margin: 0;
}
<div class="bg"></div>
Or
Cover with a pseudo element
If you want to create a radial gradient with two halves of different color, you can use a pseudo element with half the height of the parent.
.bg {
position: relative;
width: 100vh;
height: 100vh;
background: radial-gradient(circle closest-side, yellow, black);
}
.bg::before {
display: block;
position: absolute;
top: 0;
left: 0;
width: 100vh;
height: 50%;
background: radial-gradient(circle closest-side, #00bffb, black);
background-size: 100% 200%; /** we need to compensate for the 50% height **/
content: '';
}
body {
margin: 0;
}
<div class="bg"></div>
Set the gradient on half of the container with background-size: 100% 50%,
Position the gradient circle so that only its top half is visible with background-image: radial-gradient(circle 50vh at 50% 100%, #00bffb, #0000);
Explanation:
circle 50vh sets the gradient radius to half the size of the container (you need to use a fixed size, thus 50vh, or 200px if your container was 400px tall — % won't work, sadly)
at 50% 100% sets the gradient center in the middle of the bottom edge of the background box.
body {
width: 100vh;
height: 100vh;
background-color: #000;
background-image: radial-gradient(circle 50vh at 50% 100%, #00bffb, #0000);
background-size: 100% 50%;
background-repeat: no-repeat;
}
https://codepen.io/hyvyys/pen/xxKRGwP
Basically I want to create a shape in CSS only (so no images) that is the opposite of a heart shape. I don't know how to explain it properly so here is an image:
The blue is the background, as you can see, but the shape that I want to create is not a heart, it is the shape of the black rectangle.
If I would have the following shape (THE GRAY NOT THE BLACK)
I could duplicate it and then rotate it, that would give me the shape I am looking for.
Heart shape cut out using box-shadow
Let's create this — the blue is the background color of <body>
The pieces
Feel free to skip directly to the complete demo at the bottom of this answer :)
1 - The rounded corners
The rounded top left and top right corners are created with box-shadow on the two pseudo elements with border-radius: 50% — .heart:before and .heart:after — They form two crescent shapes that look like this:
2 - The angle
The angled shape is created by the box-shadow on .heart. Combined with the two circles, it looks like this:
3 - The filler
We now need to fill in the gaps. This is done by the pseudo elements of the .box-shape container — .shape-box:before and .shape-box:after. The excess is cut-off neatly with overflow: hidden on the .shape-box. Combined with our pieces above, they look like this:
The Complete Example
Combine it all together and we get this nicely cut out heart shape. It is all contained in .shape-box.
body {
background: #00A2F6;
}
.shape-box {
height: 504px;
width: 504px;
position: relative;
margin: 100px;
overflow: hidden;
}
.shape-box:before,
.shape-box:after {
content: '';
display: block;
height: 100px;
width: 120px;
background: #2B2B2B;
transform: rotate(45deg);
left: 190px;
position: absolute;
top: 40px;
}
.shape-box:after {
width: 760px;
height: 750px;
box-shadow: inset 0 0 0 220px #2B2B2B;
top: -150px;
left: -130px;
background: none;
}
.heart {
transform: rotate(45deg);
height: 357px;
width: 356px;
box-shadow: inset 0 0 0 50px #2B2B2B;
position: absolute;
left: 74px;
top: 34px;
}
.heart:before,
.heart:after {
content: '';
display: block;
width: 151px;
height: 151px;
border-radius: 50%;
box-shadow: -40px -15px 0 20px #2B2B2B;
position: absolute;
left: 50px;
top: 157px;
}
.heart:after {
box-shadow: -15px -40px 0 21px #2B2B2B;
left: 156px;
top: 51px;
}
<div class="shape-box">
<div class="heart"></div>
</div>
This can be done with a combination of svg gradients, multiple backgrounds, and a little creative tiling/placement. Sample CSS from my working jsfiddle (without vendor prefixes, i.e. -webkit and -moz):
height: 400px;
width: 400px;
background-image:
radial-gradient(75% 85.5%, circle, transparent 25%, black 26%),
radial-gradient(25% 85.5%, circle, transparent 25%, black 26%),
linear-gradient(225deg, transparent 25%, black 25%),
linear-gradient(135deg, transparent 25%, black 25%);
background-size: 200px 200px;
background-position: top left, top right, bottom left, bottom right;
background-repeat: no-repeat;
This makes a heart-shaped cutout in the middle of a 400px square element. It can be modified to fit whatever size element you want.
Update: here’s a more complex fiddle that uses six gradients instead of four, but looks a bit nicer.
Based on the work that Mark Hubbart did I was able to push this to a slightly more advanced form in this fiddle
This is not 100% complete yet as it will need some media queries to work across more browsers but it does show the start of a much more flexible working for the same goal.
#backgrounder {
z-index: 2;
background-image:
radial-gradient(68% 100%, circle, transparent 48%, white 30%),
radial-gradient(32% 100%, circle, transparent 48%, white 30%),
radial-gradient(110% 1%, circle, transparent 65%, white 30%),
radial-gradient(-8.5% 1%, circle, transparent 65%, white 30%),
linear-gradient(220deg, transparent 41%, white 30%),
linear-gradient(139deg, transparent 41%, white 30%);
background-image:
-webkit-radial-gradient(68% 100%, circle, transparent 48%, white 30%),
-webkit-radial-gradient(32% 100%, circle, transparent 48%, white 30%),
-webkit-radial-gradient(110% 1%, circle, transparent 65%, white 30%),
-webkit-radial-gradient(-8.5% 1%, circle, transparent 65%, white 30%),
linear-gradient(220deg, transparent 41%, white 30%),
linear-gradient(139deg, transparent 41%, white 30%);
background-size: 51% 31%, 50% 31%, 51% 50%, 50% 50%, 51% 51%, 50% 51%;
background-position: top left, top right, 0% 30%, 100% 30%, bottom left, bottom right;
background-repeat: no-repeat;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}
I'm working on a HTML/CSS/JS project where the app is a fixed size and elements must be positioned precisely, based on the designs. Because the window size is fixed, I can easily work with pixel dimensions in CSS and not worry about resizing the browser. I also have the luxury of not worrying about IE or Opera: the app must work in webkit and firefox only.
In a few places, I need to have a gradient background going over specific number of pixels. This would be easily accomplished with something like
background-image: linear-gradient(to top, #666666, #000000 60px);
(and its -webkit- and -moz- counterparts.) This does the trick for most elements. However there are a couple where I need to have the top and bottom pixel positions for colour stops. If these were percentage points, then it could be done with something like:
background-image: linear-gradient(to top, #666666, black 60px, transparent 60px, transparent 90%, black 90%, #666666);
(from grey to black over 60px, then transparent and then black to grey over the last 10%). However I need to accomplish the same with pixels, as the element in question is sized differently at different times. I'd like to avoid having to use JS to re-apply the gradient at different dynamically calculated percentage points if needed.
So, my question: is there a way to specify a colour stop x pixels (not percentage) from the end?
I just came over this via search engine, i think the best solution was already given by vals with using multiple background images - but instead of using background-size and background-position i think it's a lot more flexible and stable to use alpha colors here (with rgba()), like in the example below:
background-image:
/* top gradient - pixels fixed */
linear-gradient(to bottom, rgb(128,128,128) 0px,rgba(128,128,128,0) 16px),
/* bottom gradient - pixels fixed */
linear-gradient(to top, rgb(128,128,128) 0px, rgba(128,128,128,0) 16px),
/* background gradient - relative */
linear-gradient(to bottom, #eee 0%, #ccc 100%) ;
This gives me exactly the behaviour I was initially searching for. :)
Demo: http://codepen.io/Grilly86/pen/LVBxgQ
It works with calc(), but unfortunately not in MS browsers:
First row of each pairs has the solution with 2 background stacked, 2nd row has calc in use. Does not work with Internet Explorer and Edge browsers.
div {
margin-left: auto;
margin-right: 0;
width: 200px;
height: 20px;
animation: sweep 5s ease-in-out alternate infinite;
text-align: center;
color: white;
font-family: sans-serif;
font-weight: bold;
line-height: 20px;
will-change: width;
}
div:nth-child(odd) {
background-image: linear-gradient(to right, red, green 100px, transparent 101px), linear-gradient(to left, red, green 100px);
border-bottom: 1px solid gray;
}
div:nth-child(even) {
background-image: linear-gradient(to right, red, green 100px, green calc(100% - 100px), red);
margin-bottom: 10px;
}
div:nth-child(n+3) {
width: 300px;
}
div:nth-child(n+5) {
width: 400px;
}
div:nth-child(n+7) {
width: 500px;
}
div:nth-child(n+9) {
width: 600px;
}
#keyframes sweep {
100% {
width: 600px;
}
}
<div> 200 </div>
<div></div>
<div> 300 </div>
<div></div>
<div> 400 </div>
<div></div>
<div> 500 </div>
<div></div>
<div> 600 </div>
<div></div>
I don't think this is possible, but overlaying 2 objects, one with opaque pixels from bottom and the other with pixels from top, would still avoid using JS
.background {
position: absolute;
background-image: linear-gradient(to top, #666666, black 60px, transparent 60px);
}
.overlay {
position: relative;
background-image: linear-gradient(to bottom, #666666, black 60px, transparent 60px);
}
In the line of the previous answer from po228, but in the same element background.
Set 2 different gradients, one starting from top and the other from bottom
.test {
background: linear-gradient(to top, red 10px, white 10px),
linear-gradient(to bottom, blue 10px, white 10px);
background-size: 100% 50%;
background-repeat: no-repeat;
background-position: bottom center, top center;
height: 150px;
width: 300px;
}
<div class="test"></div>