If you're looking to create a unique border shape, consider using a pseudo element.
- Start by removing the
border
from the actual Box
and add it to the pseudo element instead.
- Give the stacking context a non-
auto
z-index
value to position the pseudo element behind content while keeping it visible.
- Eliminate the top-left
border-radius
as we will be crafting our chamfered edge.
<Box sx={{
position: 'relative',
zIndex: 0,
width: '360px',
height: '506px',
borderRadius: '0 30px 30px 30px',
boxShadow: `10px 10px 0px ${palette.black[900]}`,
}} />
To style the pseudo element:
- Make it fill the parent element with
position: absolute; inset: 0
.
- Ensure it sits behind all content by giving it a negative
z-index
.
- Transfer the
border
properties to the pseudo element.
- Inherit the parent's
border-radius
.
<Box sx={{
…
'&::before': {
position: 'absolute',
inset: 0,
zIndex: -10,
border: `3px solid ${palette.black[900]}`,
borderRadius: 'inherit',
content: '""',
},
}} />
Next, let's add the clip-path
for the chamfered edge:
<Box sx={{
…
'&::before': {
…
clipPath: 'polygon(100% 0, 100% 100%, 0 100%, 0 150px, 150px 0)',
},
}} />
The issue arises when the border
doesn't follow the clip-path
. To work around this, use a background linear-gradient()
:
<Box sx={{
…
'&::before': {
…
background: 'linear-gradient(135deg, black 50%, transparent 50%) no-repeat top left / 149px 149px',
},
}} />
Here's the complete example of how to achieve this effect:
const { Box } = MaterialUI;
const palette = { black: { '900': '#000' } };
function App() {
return (
<Box sx={{
position: 'relative',
zIndex: 0,
width: '360px',
height: '506px',
borderRadius: '0 30px 30px 30px',
boxShadow: `10px 10px 0px ${palette.black[900]}`,
'&::before': {
position: 'absolute',
inset: 0,
zIndex: -10,
border: `3px solid ${palette.black[900]}`,
borderRadius: 'inherit',
content: '""',
clipPath: 'polygon(100% 0, 100% 100%, 0 100%, 0 150px, 150px 0)',
background: 'linear-gradient(135deg, black 50%, transparent 50%) no-repeat top left / 149px 149px',
},
}} />
);
}
ReactDOM.createRoot(document.getElementById('app')).render(<App/>);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://unpkg.com/@mui/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cca1adb8a9bea5ada08cbaf9e2fdf8e2fd">[email protected]</a>/umd/material-ui.production.min.js"></script>
<div id="app"></div>