I've cut out an image of a person and I would like to use overflow: hidden to hide the bottom of the image along the line of my container so that it looks like the image is inside the container, but then allow it to expand out of the container on the top. So essentially, overflow-bottom: hidden would be ideal, but to the best of my knowledge that doesn't exist.
If I could figure out the math to make a clip-path: polygon() the same as my border-radius: 84% 38% 70% 43% / 55% 74% 59% 71%;, I think that would work, but I haven't managed so far.
.
Any suggestions on the best way to do this?
.avatar--container {
border-radius: 84% 38% 70% 43% / 55% 74% 59% 71%;
background-color: var(--pink);
border: 20px solid var(--blue);
height: 15rem;
width: 25rem;
}
.avatar {
width: 35rem;
transform: translate(-10rem, -12rem);
margin-bottom: 5rem;
}
<div className="avatar--container">
<img className="avatar" src={src} alt="Rachel Hall" />
</div>
In order to hide bottom overflow while showing an overflow at the top, the trick is to:
Put both image and clipped container inside a single parent element.
Set a fixed height to the parent element
Position clipped element to be behind image using negative z-index
Add an extra clipped element with border and a transparent background so this would act as an overlay for the bottom of the overflowing element.
body{
background-color: #ffdfe9;
}
.main {
height: 26rem;
width: 30rem;
overflow: hidden;
}
div.avatar--container {
border-radius: 84% 38% 70% 43% / 55% 74% 59% 71%;
background-color: #ff5d8f;
border: 20px solid #a2d2ff;
height: 15rem;
width: 25rem;
overflow: hidden;
position: absolute;
top: 10rem;
z-index: -1;
}
div.avatar--container.c2 {
background-color: transparent;
background-color: transparent;
border-left: 20px solid #a2d2ff;
border-right: 20px solid #a2d2ff;
border-bottom: 20px solid #a2d2ff;
border-top: 20px solid transparent;
z-index: 1;
}
.avatar {
width: 30rem;
}
<div class="main">
<img class="avatar c2" src="https://www.freeiconspng.com/uploads/female-model-png-model-png4-by-icekitz-3.png" alt="Rachel Hall" />
<div class="avatar--container c2">
</div>
<div class="avatar--container">
</div>
</div>
body {
background-image: linear-gradient(
0deg,
var(blue) 70%,
var(red) 30%
)
no-repeat;
height: 100vh;
}
1) How to add a border-radius at the exact bottom left and right corners of the red background-color?
As i require the border-radius in the red color which is part of the
linear-gradient, i don't know how.
Its just on the body element.
This snippet puts the red background onto the after pseudo element which is given 30% of the overall height of the body and has the two bottom corners rounded.
The before pseudo element is given the blue background.
body {
--blue: blue;
--red: red;
height: 100vh;
width: 100vw;
}
body::before,
body::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: -1;
}
body::before {
background-color: blue;
height: 100%;
}
body::after {
height: 30%;
background-color: var(--red);
border-radius: 0 0 20px 20px;
}
<body></body>
It is possible to combine linear and radial gradients to get a rounded effect, but I find the result isn't always as crisp as using border rounding.
I tried to make a hole area in the bottom corner of the overlay like in the image below, but still having trouble.
here is an example of the code
<div className="container h-screen bg-overlay fixed z-50 opacity-90 holes">
</div>
.holes::before {
content: "";
display: block;
/* Scale */
width: 50px;
padding: 10px 0px;
/* Position */
position: absolute;
top: 90%;
right: 60%;
z-index: 2;
/* Border */
border: solid 80px rgb(255,255,255);
border-radius: 50%;
opacity: 0.7;
}
but the code above still doesn't fit because it doesn't make a hole in the lower left corner but makes a new hole with a pseudo class
It can be achieved using pseudo classes. Just an after or before can be used if you are not expecting it to emit any events.
Do you require a complete circle or a half one?
.container {
width: 100%;
height: 300px;
position: relative;
background-color: blue;
}
.round {
position: absolute;
display: inline-flex;
justify-content: center;
align-items: center;
content: '';
width: 100px;
height: 100px;
border-radius: 50%;
border: 5px solid yellow;
background-color: #fff;
bottom: -50px;
left: 50px;
color: #777;
font-size: 16px;
}
<div class='container'>
<span class='round'>UPLOAD</span>
</div>
EDIT
Added text inside the round
You can use CSS mask to cut a hole in an element with a radial-gradient as the mask image. You can put the yellow border around the hole with a background radial gradient at the same place.
This snippet has a container background of magenta so you can see that a genuine 'hole' is cut with whatever is below being shown (though the background radial gradient will cover it with a transparent layer).
Note: view the snippet in Full page
.container {
background-color: magenta;
display: inline-block;
width: 100vw;
height: 100vh;
}
.div {
-webkit-mask: radial-gradient(circle at 50px 100%, transparent 0, transparent 50px, black 50px, black 100%);
mask: radial-gradient(circle at 50px 100%, transparent 0, transparent 50px, black 50px, black 100%);
background-color: skyblue;
background-image: radial-gradient(circle at 50px 100%, transparent 0, transparent 50px, yellow 50px, yellow 53px, transparent 53px, transparent 100%);
width: 100%;
height: 300px;
margin: 0;
padding: 0;
}
<div class="container">
<div class="div"></div>
</div>
Imagine that we have two layers of background.
The bottom layer is green <div class="green"></div>. For simplicity, let's assume it's just a color. But in my project, this layer contains a css animation.
And another layer of blue goes on top of it <div class="blue"></div>.
Now, I want to have another div that goes on top of both, and it reveals the green background (animation layer in my project).
The closest example I can think of is if you imagine a spotlight. Everything seems black, and the spotlight moves around and reveals the background.
Essentially, that's what I have:
<div class="green">
<div class="blue">
<div class="reveal"></div>
</div>
</div>
It will look something like this. Just remember, the green layer is an animation in my project.
QUESTION: how can I complete the .reveal styles to achieve the above behavior.
First div - draws .green background (animation)
Second dv - draws .blue background goes on top of it
Third/Fourth/... divs - Goes on top of both, but it reveals whatever the background First div draws
Note: First and Second div covers 100% of the available width and height.
.green {
background-color: #159c82;
width: 100vw;
height: 100vh;
}
.blue {
background-color: #1b4287;
// I could change this to a sibling div and use,
// position: absolute; but that seems unnecessary
width: 100%;
height: 100%;
}
.reveal {
margin-top: 10px;
margin-left: 10px;
width: 200px;
height: 50px;
// not sure what else to put here to make it work
}
<div class="green">
<div class="blue">
<div class="reveal"></div>
</div>
</div>
P.S. There is one approach I found that I did not like at all.
Use mask to create a hole and no need for the reveal div. You can later change the size and position to have the animation you want:
.green {
background: linear-gradient(45deg,#159c82,red);
height: 100vh;
}
.blue {
background:#1b4287;
height: 100%;
-webkit-mask:
/* you adjust this */
linear-gradient(#fff,#fff)
50px 50px/ /*left top*/
200px 20px, /*width height*/
/**/
linear-gradient(#fff,#fff);
-webkit-mask-repeat:no-repeat;
-webkit-mask-composite: destination-out;
mask:
/* you adjust this */
linear-gradient(#fff,#fff)
50px 50px/ /*left top*/
200px 20px, /*width height*/
/**/
linear-gradient(#fff,#fff);
mask-repeat:no-repeat;
mask-composite:exclude;
transition:.5s;
}
.blue:hover {
-webkit-mask-position:100px 100px,0 0;
mask-position:100px 150px,0 0;
-webkit-mask-size:300px 50px,auto;
mask-size:300px 50px,auto;
}
body {
margin: 0;
}
<div class="green">
<div class="blue">
</div>
</div>
You can also add as many mask as you want:
.green {
background: url(https://picsum.photos/id/1018/800/800) center/cover;
height: 100vh;
}
.blue {
background:#1b4287;
height: 100%;
-webkit-mask:
/* 3rd mask */
radial-gradient(farthest-side,#fff 99%,transparent)
top 50px right 50px/
100px 100px,
/**/
/* 2nd mask */
linear-gradient(#fff,#fff)
bottom 50px right 50px/
300px 20px,
/**/
/* 1st mask */
linear-gradient(#fff,#fff)
50px 50px/
200px 20px,
/**/
linear-gradient(#fff,#fff);
-webkit-mask-repeat:no-repeat;
-webkit-mask-composite: destination-out;
mask:
/* 3rd mask */
radial-gradient(farthest-side,#fff 99%,transparent)
top 50px right 50px/
100px 100px,
/**/
/* 2nd mask */
linear-gradient(#fff,#fff)
bottom 50px right 50px/
300px 20px,
/**/
/* 1st mask */
linear-gradient(#fff,#fff)
50px 50px/
200px 20px,
/**/
linear-gradient(#fff,#fff);
mask-repeat:no-repeat;
mask-composite:exclude;
transition:.5s;
}
.blue:hover {
-webkit-mask-position:
100px 100px,
bottom 100px left 50px,
top 50px right 50px,
0 0;
mask-position:
100px 100px,
bottom 100px left 50px,
top 50px right 50px,
0 0;
-webkit-mask-size:
150px 150px,
50px 50px,
300px 50px,
auto;
mask-size:
150px 150px,
50px 50px,
300px 50px,
auto;
}
body {
margin: 0;
}
<div class="green">
<div class="blue">
</div>
</div>
A techhnique that will work, with an even simpler layout, is box-shadow
.layer1 {
width: 100%;
height: 100%;
position: absolute;
background-image: linear-gradient(yellow, blue);
background-size: 200% 200%;
animation: bkg 2s infinite alternate;
background-origin: padding-box;
}
.layer2 {
width: 200px;
height: 200px;
position: absolute;
background: transparent;
border-radius: 30px;
left: 20px;
top: 40px;
box-shadow: 0px 0px 0px 10000px blue;
}
#keyframes bkg {
from {
background-position: 0 0;
}
to {
background-position: 100% 100%
}
}
<div class="layer1"></div>
<div class="layer2">
</div>
Also, you have a posibility to achieve this using blending.
The main disadvantage is that this uses hard-light , son the colors used in layer2 are limited to having 0 or 255 for the primary colors (red blue and green).
It will work for pure red (255, 0,0), green (0, 255, 0), blue (0, 0, 255), and also (255, 255, 0), (255, 0, 255), (0, 255, 255)
But it has the advantage that you can set severial divs to act as windows
.layer1 {
width: 100%;
height: 100%;
position: absolute;
background-image: linear-gradient(yellow, blue);
background-size: 200% 200%;
animation: bkg 2s infinite alternate;
background-origin: padding-box;
}
.layer2 {
width: 100%;
height: 100%;
position: absolute;
background: rgba(0, 255, 0);
mix-blend-mode: hard-light;
}
.layer3 {
width: 200px;
height: 200px;
position: absolute;
background: grey;
border-radius: 30px;
left: 20px;
top: 40px;
}
#keyframes bkg {
from {
background-position: 0 0;
}
to {
background-position: 100% 100%
}
}
<div class="layer1"></div>
<div class="layer2">
<div class="layer3"></div>
</div>
This will work also for multiple divs:
.layer1 {
width: 100%;
height: 100%;
position: absolute;
background-image: linear-gradient(yellow, blue);
background-size: 200% 200%;
animation: bkg 2s infinite alternate;
background-origin: padding-box;
}
.layer2 {
width: 100%;
height: 100%;
position: absolute;
background: rgba(0, 255, 0);
mix-blend-mode: hard-light;
}
.layer3 {
width: 200px;
height: 200px;
position: absolute;
background: grey;
border-radius: 30px;
left: 20px;
top: 40px;
}
.layer3:nth-child(2) {
left: 120px;
top: 80px;
}
#keyframes bkg {
from {
background-position: 0 0;
}
to {
background-position: 100% 100%
}
}
<div class="layer1"></div>
<div class="layer2">
<div class="layer3"></div>
<div class="layer3"></div>
</div>
Do you want to put the reveal div in this postion only, or show the green color from the bottom layer?
for only the positon you can add realtive position in your blue div and absolute position in your reveal div with top and left values.
.green {
background-color: #159c82;
width: 100vw;
height: 100vh;
}
.blue {
background-color: #1b4287;
width: 100%;
height: 100%;
position: relative;
}
.reveal {
position: absolute;
top: 10px;
left: 10px;
width: 200px;
height: 50px;
}
If I understand you correctly you probably should use a css variable.
https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties
Editing your example we get the following.
:root {
--bottom-layer-color: #159c82
}
.green {
background-color: var(--bottom-layer-color);
width: 100vw;
height: 100vh;
}
.blue {
background-color: #1b4287;
width: 100%;
height: 100%;
}
.reveal {
margin-top: 10px;
margin-left: 10px;
width: 200px;
height: 50px;
background-color: var(--bottom-layer-color)
}
<div class="green">
<div class="blue">
<div class="reveal"></div>
</div>
</div>
cheers,
to change the color with css:
/* Use a later css file to redeclare the root variable, */
/* this will override previously declared css. */
/* https://css-tricks.com/precedence-css-order-css-matters/ */
:root {
--bottom-layer-color: powderblue
}
to change the color with javascript:
const eStyle = document.documentElement.style
eStyle.setProperty('--top-bar-height', '263px');
You can change a lot of things with css variables. Not just background-colors.
For instance
root: {
--bottom-layer-color: #159c82
--bottom-layer-radius: 50%;
/* this would make the bottom layer a circle. And reaveal a circle. */
}
.green {
background-color: var(--bottom-layer-color)
border-radius: var(--bottom-layer-color)
width: 100vw;
height: 100vh;
}
.reveal {
background-color: var(--bottom-layer-color)
border-radius: var(--bottom-layer-color)
}
/* Set --bottom-layer-radius back to 0 to make both items square again. */
This is one of the easiest things to do in CSS
<Style>
.blue {
width: 100%;
height: 300px;
background-color: lightblue;
}
</style>
<div class="blue">
</div>
After creating a clip path to mask away a part of an image leaving behind a downward pointing arrow, I get this thin line on high resolution screens or when i zoom in on a regular screen.
here is the css for the clip path:
.clearflowptr {
margin-bottom: 40px;
margin-top: 40px;
background: white;
height: 50px;
width: 100%;
-webkit-clip-path: polygon(0 0, 46% 0, 50% 100%, 54% 0, 100% 0, 100% 100%, 0 100%);
the margin-bottom and margin-top just add spacing to the element. I tried playing around with the padding but to no avail.
Any help is appreciated.
Thanks
You can try this one instead of using clip-path if its not a requirement.
div{
background-color: #0b8192;
width: 100%;
height: 15px;
position: relative;
}
div:after{
content: '';
width: 0px;
height: 0px;
border: 40px solid #0b8192;
position: absolute;
top: 100%;
left: 0;
right: 0;
margin: auto;
border-right-color:transparent;
border-left-color:transparent;
border-bottom-color:transparent;
}
<div>
</div>