Create multiple elements with CSS generated content? - css

I have a div (blue in the image below). I need to create a number of equally spaced circles within it. Can this be done with CSS generated content? I could create 2 with the :before and :after pseudo classes, but as I need more would a CSS solution requite more html elements?
I was hoping to not have to use an image to improve loading times and to optimize the site for different display density devices.
UPDATE This is for a responsive design so the width of the blue div will vary. They also need to remain equally spaced.

Well, we could create only two pseudo-elements for each element.
However, we could fake the effect by multiple box-shadow values, as follows:
.box:after {
content: '';
display: block;
margin: 0 auto;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: orange;
box-shadow: 25px 0 0 0 orange, /* Or use positive offsets if needed */
-25px 0 0 0 orange,
50px 0 0 0 orange,
-50px 0 0 0 orange;
}
WORKING DEMO.
Update
Unfortunately, it's not possible to set a box-shadow offset relative to the width of the containing block. (The best try would be using relative em/rem units, but the font-size itself can not be changed per the width of the container)
Therefore, using radial-gradient background is the best option you'd have (as #Michal has suggested).
In order to keep the aspect ratio of the blue box, you could set the height to 0 and use a percentage value for padding-top which relies on the width of the containing box.
.box {
background: orange radial-gradient(closest-side, transparent 40%, skyblue 0%);
background-size: 20% 100%;
width: 100%;
height: 0; /* Make sure that the box has no height */
padding-top: 20%; /* Keep 5:1 aspect ratio */
}
Here is the WORKING DEMO.

You could simply use radial-gradient.
.circles {
/* red: color of the circles */
background-color: red;
/* 40%: size of circles proportionally to size of an element they reside in */
/* blue: color of the background */
background-image: radial-gradient(closest-side, transparent 40%, blue 0%);
/* 20%: width of circle, so 5 in row */
/* 100%: height of circle, so 1 in column */
background-size: 20% 100%;
/* 20%: keep the aspect ration 5:1 for dynamic layout */
padding-bottom: 20%; /* or padding-top */
/* 100%: fill up given space */
width: 100%;
/* 0: so the possible content doesn't distort the aspect ratio */
height: 0;
}
Demo on http://jsfiddle.net/Gobie/t6X3Z/3/

If you place several nested divs inside your container div you can use border-radius to create the circles. Something like this should do the trick:
HTML
<div id="container">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
CSS
#container {
width: 300px;
height: 100px;
background-color: blue;
}
.circle {
border-radius: 50%;
width: 50px;
height: 50px;
background-color: red;
margin: 10px;
display: inline-block;
}
Here is a fiddle of it in action: http://jsfiddle.net/GXL3w/

Related

How to make a clipped half circle (D shape) using CSS?

I need help understanding clip-path CSS property in order to make my version of a clipped circle below...
More like the design version:
If you can see on the grey background, my circle appears a lot larger and less round when it's clipped.
What can I do to make a more round circle? My ideas were:
Use clip-path as in the snippet below
Use a pseudo :after element or a right border with radius
Cut a circle image from photoshop and use it as a background image.
Preferably, I'd like to avoid using a background image. However, I need to keep responsiveness in mind as the circle cannot change shapes drastically as we resize the window.
Is clip-path the right way to go? Can someone suggest a simpler and elegant solution with another way using CSS?
Thank you in advance, here's a snippet I wrote that illustrates how I clipped the "green/blue" background:
.page-banner {
background: grey;
width: 100%;
height: 300px;
background-position: top;
overflow: hidden;
}
.page-banner-text {
position: absolute;
background: #00525d8a;
padding-left: 100px;
width: 60%;
/* adjustments to snippet */
top: 10px;
left: 10px;
height: 300px;
/* this is the code for circle */
clip-path: circle(560px at left);
padding-right: 250px;
}
<div class="page-banner">
<div class="container">
<div class="page-banner-text">
<h1 class="block-title">Programs For Adults</h1>
<p>Programs to help children with disabilities in Western MA at all ages and levels of need.</p>
<div id="banner-donate-button">DONATE</div>
</div>
</div>
</div>
Per my comment, instead of using clip path to create your D (which is not supported very well), why not use border radius on your div.
* {
box-sizing: border-box;
}
.page-banner {
position: relative;
background: url(https://www.fillmurray.com/300/900) center center no-repeat;
background-size: cover;
width: 100%;
overflow: hidden; /* hide overflowing bits of circle */
min-height: 300px; /* just give enough height to fit text at smallest screen width size */
}
.circle {
background-color: rgba(50, 108, 116, 0.9); /* use rgba for transparent effect */
color: white;
transform: translate(-50%, -50%); /* move the circle left 50% of it's own width and up 50% of it's own height */
border-radius: 50%;
padding-top: 100%; /* this gives us a responsive square */
position: absolute;
top:50%; /* this vertically centers the circle */
left:0;
width:100%;
min-width:600px; /* this is the miniimum dimensions to allow circle to fill smaller screens */
min-height:600px;
}
.page-banner-text {
position: absolute; /* just positions the text on the right of the cirecle */
left: 50%;
top: 50%;
transform: translateY(-50%);
padding:2em;
width:40%;
}
<div class="page-banner">
<div class="circle">
<div class="page-banner-text">
<h1 class="block-title">Programs For Adults</h1>
<p>Programs to help children with disabilities in Western MA at all ages and levels of need.</p>
<div id="banner-donate-button">DONATE</div>
</div>
</div>
</div>
The only problem with it being responsive though is that as the screen gets wider, the D gets flatter (as the radius extends), but you can combat this by adding a max width and height to the circle div
To anyone looking to solve this with the clip-path property, you have a bit more control with the ellipse clip path. Using the code provided by the OP, I replaced circle with ellipse, and switched to percentages to allow for a slightly better responsive feel.
clip-path:ellipse(67% 100% at 8% 50%);
The first two numbers represent the height and width of the ellipse. The larger the first number, the wider the visible area is. The larger the second number, the wider the height. We're aiming for a D shape, so by adjusting the first number, we can make the D more or less prominent.
This is where the second two numbers, the positioning, comes into play. at 50% 50% centers it. By adjusting the first number, the X positioning, we can move it over where need fit . After playing around with the numbers, you should be able to get the D exactly how you'd like.
.page-banner {
background: grey;
width: 100%;
height: 300px;
background-position: top;
overflow: hidden;
}
.page-banner-text {
position: absolute;
background: #00525d8a;
padding-left: 100px;
width: 60%;
/* adjustments to snippet */
top: 10px;
left: 10px;
height: 300px;
/* this is the code for circle */
clip-path: ellipse(67% 100% at 8% 50%);
padding-right: 250px;
}
<div class="page-banner">
<div class="container">
<div class="page-banner-text">
<h1 class="block-title">Programs For Adults</h1>
<p>Programs to help children with disabilities in Western MA at all ages and levels of need.</p>
<div id="banner-donate-button">DONATE</div>
</div>
</div>
</div>
You could simply use
an inner circle element, which you can achieve with a border-radius equal to half the element's height and width
positioned via position: relative with negative top and left values
inside of an outer bounding box, clipped via overflow: hidden
A simple implementation:
#container {
height: 300px;
width: 100%;
background-color: gray;
overflow: hidden;
}
#circle {
height: 600px;
width: 600px;
background-color: rgba(0, 0, 255, 0.5);
position: relative;
top: -150px;
left: -375px;
}
<div id="container">
<div id="circle"></div>
</div>

Background image with a colored curved border at the bottom

I am trying to achieve this with css3, I tried using border-radius with percent values and it's not the same always, I always got a rounded corners and the border will start disappearing on the corners too.
I want it to be exactly the same as the example image:
EDIT:
this is my html code :
<div class='container-fluid'>
<section class='section-1'>
<div class='container'>
</div>
</section>
And this is my css:
.section-1 {
background-image: url('../images/bg.png');
background-size: cover;
background-repeat: no-repeat;
position: relative;
background-position: 50%;
}
If you want, you can accomplish this using only CSS by creating a <div> that would be used only as a mask. You can create the round effect with the border-radius property, but you need to do it bigger than the part that will be visible, then crop the result to show only the curvy part that you want. And you must compensate the imagem position.
Check my example below:
.oval-header {
width: 100%;
height: 150px;
overflow: hidden;
position: relative
}
.oval-header--mask {
width: 200%; /* Mask width 2x the size of the header */
height: 200%; /* Mask height 2x the size of the header */
transform: translate(-25%, -51%); /* This compensates the size of the image and places the curvy part that you want on the certer of the mask, it's a translate that negativates half it's width and half it's height */
border: 6px solid yellow;
border-radius: 0 0 50% 50%;
overflow: hidden;
border-top: 0;
background-image: url('http://www.placecage.com/3000/1500');
background-size: cover
}
<div class="oval-header">
<div class="oval-header--mask">
</div>
</div>

Title-safe covering background image

Since a little while we have the awesome background-size: cover and background-size: contain CSS properties.
What I'm looking for is a way to implement a combination of both. Lets call it the 'title-safe' area.
Basically in my background there is on each axis an area that is fine if it disappears/crops if the bounding box is not the appropriate size, but there's an inner area that absolutely must be visible, and we can use letterboxing to ensure this is true.
Some more info:
My background image has a 3:2 aspect ratio.
For example, this could be 300 x 200px.
Viewed on a 4:3 screen, this would become 266.66 x 200px
Viewed on a 16:9 screen, this becomes 300 x 168.75 px
The inner box inside both these 4:3 and 16:9 ratios is an area of 266.666 x 168.75 px. I want to make sure that if people watch the image on other/weirder aspect ratios that inner area remains visible at all times, and I'm calling this the 'title safe area'.
You can have 3 separate styles, and change them with media queries based on the aspect ratio
I have also changed the border color so that it's easy to know which style applies
html, body {
height: 100%;
}
.test {
width: 90%;
height: 90%;
border: solid 2px black;
margin: auto;
background: url(http://i.stack.imgur.com/ZmhEE.jpg);
background-position: center;
background-repeat: no-repeat;
background-size: contain; /* changed by media queries */
}
#media screen and (min-aspect-ratio: 16/9) {
.test {
border: solid red 2px;
background-size: auto 120%;
}
}
#media screen and (max-aspect-ratio: 4/3) {
.test {
border: solid green 2px;
background-size: 120% auto;
}
}
<div class="test"></div>
I figured it out.
Take the following example for a html document:
<div class="container">
<div class="inner">
</div>
</div>
The inner css class will get a background-image that's always in the 3:2 aspect ratio.
The container has the following CSS rules. Note that the width and height are static here, but they can have any value, including percentages You can tweak them to ensure that the system works.
.container {
width: 900px;
height: 450px;
overflow: hidden;
}
Then the inner css needs the following rules to behave correctly:
.inner {
/* Set the background image. Must be 3:2 aspect ratio! */
background-image: url('background.jpg');
/* Fill up the container.*/
width: 100%;
height: 100%;
/* This is the default in any browser, but many people set it to
border-box these days for every element. It must be "content-box"
for this to work. The key thing here is that the width/height
cannot include the padding.
*/
box-sizing: content-box;
/* Normal CSS contain behavior */
background-size: contain;
background-repeat: no-repeat;
/* Always go to the center */
background-position: center center;
/* This will cause the background to extend beyond the content and
into the padding.
*/
background-clip: padding-box;
/* These numbers are just based on trial and error and not exact.
I tried to figure it out with Math, but my math was wrong. These
are fairly close approximations.
Effectively the width + the padding becomes the total 3:2 image
and the total image MINUS the padding = the title safe area.
*/
padding: 6% 8% 6% 8%;
/*
These margins ensure that the image is still centered.
The overflow:hidden on the container element make sure that
there's no scrollbars.
*/
margin-left: -8%;
margin-top: -6%;
}

How to extend border to the bottom of page?

http://jsbin.com/huzem/1/edit?html,css,output
In the above site how do i extend the border to the bottom of the page, compared to where it ends now(right at the edge of the content)? Also is there a way to make the border line up on the edge of the right and left sides of the screen without using negative values for margin such as i did by setting margin -right and margin-left to -4%?
You are setting the width to 93%, and then you are overriding that with your -4% thing - so, just don't do the first part. body has a margin of something by default: so get rid of that:
Put a border on your html and body, like - red. and look at what is actually going on. The body only stretches to fit your content... so you need to tell it how big it can be... (100%) then you have to tell the things inside what to do etc... This isn't the complete / perfect answer --- but it should get you closer to your goal.
html, body {
height: 100%; /* remind these guys they can be as tall as the viewport if they want */
}
body{
margin: 0; /* remove default margin */
color: white;
background-color: black; /* white on white is no helpful */
}
#main{
height: 100%;
}
#content{
border: solid white; /* you need a px value */
min-height: 100%;
}
a {
color:white; /* you don't need to specify for every state */
}
I suggest you to set the main div at the height of the window and set a height property to 100% to your content div like this :
#main {
width: 93%;
margin: -2% auto 0% auto;
position: absolute;
top: 0;
bottom: 0;
}
#content {
border: solid white;
margin: 0% -4% 1000% -4%;
height: 100%;
}
The border will now extend to the bottom of the page!

background position for background color

Im able to give the start position of an background image. But if i give positions for solid fill background its not working.
Here is the js fiddle for that.
http://jsfiddle.net/yPVJE/
So can we set the start position and the size of an solid fill backgrounds?
Thanks!
I would take a similar approach to StuR, but using background position instead of gradient points. You can then set your background position as you would usually.
div {
background:linear-gradient(left, #000, #000) no-repeat 50px 50px;
}
This is one way to offset a solid background color, using a linear gradient with a transparent colour for the first x number of pixels:
.offset {
background-image: linear-gradient(left, transparent 300px,rgba(39,39,39,.5) 300px, rgba(39,39,39,.5) 100%);
width: 100%;
height: 500px;
}
Here's a demo on JSFiddle.
You can not offset a background color. Only background images have a position.
If you can make a ::before pseudo element with bg color, height and width and just offset it from its parent, you'll have complete control of its appearance. Much easier than putting a border in the pseudo element:
/* adding a ::before element with bg and border radius to create a
cropped circle to overlay parent bg image's blue right end */
.myElement::before {
background-color: #fff;
content: "";
margin: 0 auto;
position: absolute;
top: 43px;
right: 0;
width: 300px;
height: 201px;
z-index: -1;
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
Yes, with linear-gradient it works:
div { background-image: linear-gradient(transparent 10px, grey 10px); }
Watch out for improper alignment when linear-gradient points are used.
Here's a better approach:
background: linear-gradient(#6699cc, #6699cc);
background-size: auto 4em;
background-repeat: no-repeat;
It uses linear-gradient just to generate solid color, which is then resized to reflect the covered area size.
Also background-position could be used as needed, for example:
background: linear-gradient(#6699cc, #6699cc);
background-size: calc(100% - 30px) auto;
background-repeat: no-repeat;
background-position: right;
In the last example, the background color would 'start' 30px from the left of the div.
Further reading:
https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient
https://developer.mozilla.org/en-US/docs/Web/CSS/background-size
https://developer.mozilla.org/en-US/docs/Web/CSS/calc
https://developer.mozilla.org/en-US/docs/Web/CSS/background-repeat
https://developer.mozilla.org/en-US/docs/Web/CSS/background-position
You can use background-size instead of background-position to restrict the colored area:
// randomly set background size every 1 second
var elm = document.querySelector('div');
window.setInterval(()=> {
var randomValue = Math.random()*100;
elm.style.backgroundSize = randomValue + '%';
}, 1000)
div {
height: 100px;
border: 1px solid black;
transition: .4s ease-out;
background: linear-gradient(to right, black, black) no-repeat;
background-size: 0; /* <--- starting from 0% */
}
<div></div>
Another way to accomplish this would be to add a pseudo-element to the div element like so:
div {
::before {
border-top: 10px solid #0066a4;
content:"";
margin: 0 auto; /* this centers the line to the full width specified */
position: absolute; /* positioning must be absolute here, and relative positioning must be applied to the parent */
top: 12px; left: 0; right: 0; bottom: 0;
z-index: -1;
}
}
See this CodePen by Eric Rasch for a working example: https://codepen.io/ericrasch/pen/Irlpm
You can achieve this by having the parent element and child element position: relative;. Next, you can just go in and set offsets. There are a few other ways to achieve this but this is one of the many takes.
SCSS:
HTML:
EXAMPLE:
Note this might have side effects for buttons and links. Test it for your use case. Good luck!
Happy Coding

Resources