How can i do a rectangle + octagon with full border?

Viewed 53

the shape that i want to do

CSS octagon shape with border

the shape that i have by searching in similar questions

i want the shape to have full border (like in the image). Inside this shape its gonna be more content so i need it whit out rotate or something like that, anyone know? This is the code i have so far, i am using sass, i have done a research from multiple websites and see other people similar questions what other people done in stack overflow but nothing result me useful

    <article>
        <div class='card__info--left'>
            <p>${data.origin.name}</p>
            <p>${data.location.name}</p>
            <p>${data.episode.length}</p>
        </div>
        <div class='card__info--img'>
            <img src='${data.image}' alt='${data.name}'>
        </div>
        <div class='card__info--right'>
            <h3>${data.name}</h3>
            <p>${data.status}</p>
            <p>${data.species}</p>
            <p>- ${data.type}</p>
            <p>${data.gender}</p>
        </div>
    </article>

    article {
    margin: auto;
    display: grid;
    place-content: center;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    background-color: #c92b2b6e;
    height: 90vh;
    border-top: 10px solid #c92b2b;
    border-bottom: 10px solid #c92b2b;
    ::before{
        content: "";
        position: absolute;
        top: 34px;
        left: 214px;
        border-bottom: 29px solid transparent;
        border-right: 20px solid #c92b2b;
        border-top: 29px solid transparent;
        height: 84.5vh;
        width: 0;
    }
    ::after{
        content: "";
        position: absolute;
        top: 34px;
        right: 214px;
        border-bottom: 29px solid transparent;
        border-left: 20px solid #c92b2b;
        border-top: 29px solid transparent;
        height: 84.5vh;
        width: 0;
    }
2 Answers

I have a generator for such shapes: https://css-generators.com/custom-corners/

Set the angle to be 180deg and use the full configuration for the main element and border-only configuration for the pseudo element:

.box {
  width: 500px;
  height: 300px;
  background: red;
  position: relative;
  /* copied from the generator */
  clip-path: polygon(0 80.00px,80.00px 0,calc(100% - 80.00px) 0,100% 80.00px,100% calc(100% - 80.00px),calc(100% - 80.00px) 100%,80.00px 100%,0 calc(100% - 80.00px));
}
.box:before {
  content:"";
  position:absolute;
  inset:0;
  background: blue;
  /* copied from the generator */
  clip-path: polygon(0 80.00px,80.00px 0,calc(100% - 80.00px) 0,100% 80.00px,100% calc(100% - 80.00px),calc(100% - 80.00px) 100%,80.00px 100%,0 calc(100% - 80.00px),0 80.00px,10px  calc(80.00px + 4.14px),10px calc(100% - 80.00px - 4.14px),calc(80.00px + 4.14px) calc(100% - 10px),calc(100% - 80.00px - 4.14px) calc(100% - 10px),calc(100% - 10px) calc(100% - 80.00px - 4.14px),calc(100% - 10px) calc(80.00px + 4.14px),calc(100% - 80.00px - 4.14px) 10px,calc(80.00px + 4.14px) 10px,10px calc(80.00px + 4.14px));
}
<div class="box">
</div>

If you want a general solution that can adjust to e.g. viewport dimensions then one method is to have the before pseudo element as the border color and slightly wider/taller than the element and an after pseudo element with background the required element background.

This snippet uses only CSS. Widths etc can be set as you require.

CSS clip-path is used to cut off the corners at 45degrees.

div {
  /* set these things to what you want them to be */
  /* the width of the element */
  --w: 80vw;
  /* the width of the border */
  --b: 4px;
  /* the distance in of the cutting point could be a px value if preferred */
  --d: calc(var(--w) / 25);
  /* you can fix the height in terms of the width */
  /* aspect-ratio: 3 / 1; */
  /* or in absolute units */
  /* height: 20vw; */
  /* otherwise it will adjust to content as in this demo */
  width: var(--w);
  position: relative;
  /* settings for the demo */
  margin: 10px;
  padding: 10px;
}

div::before,
div::after {
  margin: 0;
  padding: 0;
  content: '';
  z-index: -1;
  position: absolute;
}

div::before {
  background: red;
  width: calc(100% + (2 * var(--b)));
  height: calc(100% + (2 * var(--b)));
  top: calc(-1 * var(--b));
  left: calc(-1 * var(--b));
  clip-path: polygon(var(--d) 0, calc(100% - var(--d)) 0, 100% var(--d), 100% calc(100% - var(--d)), calc(100% - var(--d)) 100%, var(--d) 100%, 0 calc(100% - var(--d)), 0 var(--d));
}

div::after {
  background: yellow;
  width: 100%;
  height: 100%;
  /* border width * sin(45degrees) */
  --s: calc(var(--b) * 0.707106781);
  top: 0;
  left: 0;
  clip-path: polygon(calc(var(--d) - var(--s)) 0, calc(100% - var(--d) + var(--s)) 0, 100% calc(var(--d) - var(--s)), 100% calc(100% - var(--d) + var(--s)), calc(100% - var(--d) + var(--s)) 100%, calc(var(--d) - var(--s)) 100%, 0 calc(100% - var(--d) + var(--s)), 0 calc(var(--d) - var(--s)));
}
<div><br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br>line<br><br></div>

Related