Inverted' border-radius possible?
Not using the native border-radius
. As mentioned on MDN "Negative values are invalid". You could definitely look for a library out there which does this for you automatically (though I find the approach taken in Philip's suggested library to be particularly outdated).
Using pure CSS I have come up with an approach. The idea is to add 4 extra elements inside your container, set their background to the same color as your page background (so this will not let page content underneath filter through – for that, you’d need SVG masking or similar), and to position
them in such a way that they lie just outside of the element itself. We then apply a border-radius
which gives the affect:
#main { margin: 40px; height: 100px; background-color: #004C80; position: relative; overflow: hidden;}
#main div { position: absolute; width: 20px; height: 20px; border-radius: 100%; background-color: #FFF;}
.top { top: -10px; }.bottom { bottom: -10px; }.left { left: -10px; }.right { right: -10px; }
<div id="main"> <div class="top left"></div> <div class="top right"></div> <div class="bottom left"></div> <div class="bottom right"></div></div>
How to use inverted border-radius?
Just use before and add an element to style
div {
position: relative;
display: inline-block;
background-color: blue;
width: 10em;
height: 10em;
}
div::before{
display: block;
position: relative;
content: '';
width: 10%;
top: 15%;
height: 70%;
background-color: white;
border-top-right-radius: 1em;
border-bottom-right-radius: 1em;
}
<div></div>
CSS - How to make inverted border-bottom with curved edges?
You need to make use of border-top
instead of border-bottom
.border-curve {
width: 20em;
height: 10em;
background: transparent;
border-top: 1px solid hsl(180deg 100% 52%);
border-radius: 0.35em;
}
body {
background: gray;
}
<div class="border-curve"></div>
CSS inverse border-radius outside element's bounding box to create a mobile phone notch design
There are four ways to do that, from simple to more complex:
Adding 2 pseudoelements with
radial-gradient
.Simplest and well-supported solution. Probably the one I would use.
Adding 2 pseudoelements with
mask-image
(same as above, but with worse support).Quite similar, code-wise, to the previews one, but with really bad support (needs browser prefixes for those that support it).
Adding 2 pseudoelements with a
border-radius
,box-shadow
andbackground: transparent
.Needs a bit more code, but it looks a bit smoother, at least on
Chrome Version 78.0.3904.108
, so maybe it's worth it for you, although the difference is minimal. In any case, the shapes you can do can't be as complex as with the previous alternatives, especially if you want to work with ellipses rather than circles, like in this other question: https://stackoverflow.com/a/59278227/3723993.Using an SVG.
I think the SVG solution is not worth it here, but it would be a good alternative for more complex shapes or animated/transitioning shapes.
Here you can check the first 3 solutions:
const notch = document.getElementById('notch');const button = document.getElementById('button');const xrayCheckbox = document.getElementById('xrayCheckbox');const xrayLabel = document.getElementById('xrayLabel');const label = document.getElementById('label');
const solutions = [{ name: 'pseudoelements + radial-gradient', classes: 'notch notch-gradient'}, { name: 'pseudoelements + box-shadow', classes: 'notch notch-shadow'}, { name: 'pseudoelements + mask-image', classes: 'notch notch-mask'}];
let currentSolutionIndex = 0;let currentSolution = solutions[currentSolutionIndex];let xRayEnabled = false;
button.onclick = () => { currentSolutionIndex = (currentSolutionIndex + 1) % solutions.length; currentSolution = solutions[currentSolutionIndex]; updateLabels();};
xrayCheckbox.onchange = () => { xRayEnabled = xrayCheckbox.checked; updateLabels();};
function updateLabels() { if (xRayEnabled) { notch.className = `${ currentSolution.classes }-xray`; label.innerText = `${ currentSolution.name } (X-Ray)`; xrayLabel.innerText = 'Disable X-Ray'; } else { notch.className = currentSolution.classes; label.innerText = currentSolution.name; xrayLabel.innerText = 'Enable X-Ray'; }}
body { position: relative; overflow: hidden; height: 100vh; margin: 0;}
.phone { width: 420px; height: 800px; padding: 12px 12px 24px; position: absolute; top: 32px; left: 50%; transform: translate(-50%, 0); background: #000; box-shadow: 0 8px 32px 0 rgba(0, 0, 0, .5); border-radius: 16px;}
.screen { height: 100%; overflow: hidden; position: relative; background: #FFF; border-radius: 8px;}
.viewport { height: 100%; position: relative; overflow-x: hidden; overflow-y: scroll;}
.notch { top: 12px; left: 50%; width: 24px; height: 12px; z-index: 10; position: absolute; transform: translate(-50%, 0); background: #000; border-bottom-left-radius: 1024px; border-bottom-right-radius: 1024px;}
.notch::before,.notch::after { top: 0; width: 8px; height: 8px; content: ""; position: absolute;}
.notch-gradient-xray,.notch-shadow-xray,.notch-mask-xray { background: red;}
/* RADIAL GRADIENT SOLUTION */
.notch-gradient::before { left: -6px; background: radial-gradient(circle at bottom left, transparent 0, transparent 70%, black 70%, black 100%);}
.notch-gradient::after { right: -6px; background: radial-gradient(circle at bottom right, transparent 0, transparent 70%, black 70%, black 100%);}
.notch-gradient-xray::before { left: -6px; background: green radial-gradient(circle at bottom left, transparent 0, transparent 70%, cyan 70%, cyan 100%);}
.notch-gradient-xray::after { right: -6px; background: green radial-gradient(circle at bottom right, transparent 0, transparent 70%, cyan 70%, cyan 100%);}
/* BOX-SHADOW SOLUTION */
.notch-shadow::before { left: -6px; background: transparent; border-radius: 0 8px 0 0; box-shadow: 0 -4px 0 0 #000;}
.notch-shadow::after { right: -6px; background: transparent; border-radius: 8px 0 0 0; box-shadow: 0 -4px 0 0 #000;}
.notch-shadow-xray::before { left: -6px; background: green; border-radius: 0 8px 0 0; box-shadow: 0 -4px 0 0 cyan;}
.notch-shadow-xray::after { right: -6px; background: green; border-radius: 8px 0 0 0; box-shadow: 0 -4px 0 0 cyan;}
/* MASK SOLUTION */
.notch-mask::before { left: -6px; background: #000; -webkit-mask-image: radial-gradient(circle at bottom left, transparent 0, transparent 70%, black 70%, black 100%);}
.notch-mask::after { right: -6px; background: #000; -webkit-mask-image: radial-gradient(circle at bottom right, transparent 0, transparent 70%, black 70%, black 100%);}
.notch-mask-xray::before { left: -6px; background: cyan; -webkit-mask-image: radial-gradient(circle at bottom left, transparent 0, transparent 70%, black 70%, black 100%);}
.notch-mask-xray::after { right: -6px; background: cyan; -webkit-mask-image: radial-gradient(circle at bottom right, transparent 0, transparent 70%, black 70%, black 100%);}
.camera { top: 0; left: 50%; width: 12px; border: 4px solid #33244A; height: 12px; position: absolute; transform: translate(-50%, -50%); background: #304A58; border-radius: 1024px; box-sizing: border-box;}
#button { font-family: monospace; font-size: 16px; padding: 8px 16px; margin: 32px auto 16px; background: transparent; border: 2px solid black; display: block; border-radius: 2px;}
#xray { font-family: monospace; font-size: 16px; padding: 0 16px; text-align: center; display: block; margin: 0 0 16px; display: flex; align-items: center; justify-content: center;}
#xrayCheckbox { margin: 0 8px 0 0;}
#label { font-family: monospace; font-size: 16px; padding: 0 16px; text-align: center;}
<div class="phone"> <div id="notch" class="notch notch-gradient"> <div class="camera"></div> </div>
<div class="screen"> <div class="viewport"> <button id="button">Change Solution</button> <label id="xray"> <input id="xrayCheckbox" type="checkbox" /> <span id="xrayLabel">Enable X-Ray</span> </label> <div id="label">pseudoelements + radial-gradient</div> </div> </div></div>
Inverted border-radius?
You can add a gray square with the length of the radius you want there, and then put a white rounded div (circle) on top of it, the div having the width twice the length of the gray square.
See here: http://plnkr.co/edit/RxMMvqS74aMq018P5Jsq?p=preview (I reused your corner div, and added a circle div on top)
Experiment with the width/height of the corner and circle divs and the circle div's radius to get different rounding effects.
Here is a more rounded version: http://plnkr.co/edit/uwRZHCzAxEcQSQ2Elu6u?p=preview
Creating inverted border radius and box-shadow together
You can use a reduced code considering gradient coloration:
body {
background: silver
}
.dashed {
width: 90%;
height: 200px;
margin: 50px auto;
min-width: 250px;
background:
radial-gradient(50px at left , #0000 98%, #fff) left,
radial-gradient(50px at right, #0000 98%, #fff) right;
background-size: 51% 100%;
background-repeat: no-repeat;
filter: drop-shadow(0 0 2rem black);
}
<div class="dashed"></div>
Related Topics
How to Use a CSS Wildcard in the Middle of an Attribute Selector
Bootstrap: Align Input with Button
Changing Chunk Background Color in Rmarkdown
Symfony2 - Assetic - Load Images in CSS
Remove All Padding and Margin Table HTML and CSS
Sass Indented Syntax on Multiple Lines
Dynamically Updating CSS in Angular 2
Making Jagged Triangle Border in CSS
How to Create Fluid Trapezoid Image with CSS
Bootstrap Modal Sitting Behind Backdrop
What Is This CSS Selector? [Class*="Span"]
How to Hide Scrollbar in Firefox
Vertically Centering Content of :Before/:After Pseudo-Elements
Css: Are View Height (Vh) and View Width (Vw) Units Widely Supported