1

Just a quick question.

I need to achieve this shape for a container element ( it will have some child elements like a menu and some details)

enter image description here

The only thing I can think of is a polygon like this:

.folder {
  background: yellow;
  height: 150px;
  width: 250px;
  clip-path: polygon(0% 0%, 0% 100%, 100% 100%, 100% 11%, 46% 11%, 46% 0);
  filter: drop-shadow(0 0 0.75rem grey);
}
<div class="folder"></div>

The problem is that I don't know how I could specify border-radius to that shape or how I'll add some kind of shadow.

Do you know any way I can achieve these kind of shapes? Is it even possible with just CSS?

Thanks in advance.

eddy
  • 4,373
  • 16
  • 60
  • 94

2 Answers2

2

Here's a snippet pretty close to your needs. Note, it uses a clip-path: path('...') which is not supported by Opera atm. If Opera needs to be supported, the exact effect might be achieved only using external image. Without it border-radius for pseudo element can produce only a close look. Not sure if it is close enough. Also note, that the path itself is determined by static points coordinates, what might be unwanted. In such a case it might be generated by some JS.

<div class="folder"></div>
.folder{

  width: 420px;
  height: 310px;
  margin: 10em auto 10em;

  border-radius: 5px 25px 25px 25px;
  filter: drop-shadow(0 0 0.75rem grey);

  background: white;
  position: relative;
}

.folder::before{
    content:  '';
    position: absolute;
    top: -18px;
    width: 200px;
    height: 25px;
    background: white;
    border-radius: 25px 0 0 0;
    clip-path: path('M 0 0 L 160 0 C 185 2, 175 16, 200 18 L 0 50 z');
}
.folder::after{
  content: '';
  position: absolute;
  left:  40px;
  width: 85px;
  height: 5px;
  top: -18px;
  background: #7036E9;
  border-radius: 0 0 5px 5px;

}
Jared
  • 1,294
  • 2
  • 8
  • 13
  • Thanks it look great ! I've a got a question, what do you mean by an "external image"? Would it still be posible to use clip-path in Opera? – eddy Mar 20 '22 at 23:32
  • Sorry to bother you, could you share how do you determine the values for the path? I'm trying to create a smaller version of the card, but the part created using ::after looks funny when I reduce its width – eddy Mar 21 '22 at 00:11
  • By 'external' i mean external relatively to the styles (or embedded via url("data:image..") ). Opera doesn't support the `clip-path: path("...")` as [MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path#browser_compatibility) reports. Meanwhile [caniuse](https://caniuse.com/css-clip-path) does't. I've tested with Opera (v84) and it looks ok. You can use `clip-path` in Opera anyways, but if you care about older versions, u'll have use an 'external` SVG for a clip-path `clip-path: url(#id_of_the_shape)` like in [this article](https://www.sarasoueidan.com/blog/css-svg-clipping/). – Jared Mar 21 '22 at 00:15
  • 1
    Every nth(2n-1) int is an X coord, every second is Y. The rect we care about is from 0 0 to 200 18 (it is 18px height), so i define 4 anchor points at the corners of the rect. Then i move right-top point 40 px to the left (160 coord), and convert the right line to the curve. I've played a bit with curve control points coordinates (185 2 and 175 16) to achieve this result. And at last, i've moved the forth point at Y 50 coordinate (25 is enough actually) so the block is not cut off at left-bottom corner. If you want to make this lets say 1.2 times narrower just divide X coords by 1.2 – Jared Mar 21 '22 at 00:24
1

You can try this approach

.container {
  padding: 1em;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10em, 1fr));
  grid-gap: 2em;
}

.name {
  width: 10em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 1em;
}

.folder {
  height: 105px;
  width: 100%;
  position: relative;
  background-color: white;
  border: 1px solid gray;
  border-radius: 0 6px 6px 6px;
  box-shadow: 4px 4px 7px rgba(0, 0, 0, 0.59);
  padding: 0.25em 0.5em;
  display: flex;
  justify-content: space-around;
  align-items: center;
  flex-direction: column;
}

.folder:before {
  content: "";
  width: 50%;
  height: 12px;
  border-radius: 0 20px 0 0;
  background-color: white;
  border-top: 1px solid gray;
  border-left: 1px solid gray;
  border-right: 1px solid gray;
  position: absolute;
  top: -13px;
  left: -1px;
}
.options {
  display: flex;
  column-gap: 1em;
}
.folder::after{
  content: '';
  position: absolute;
  left:  0.8em;
  width: 4em;
  height: 5px;
  top: -0.8em;
  background: #7036E9;
  border-radius: 0 0 5px 5px;
}
<div class="container">

  <div class="folder">
    <h2 class="name">Folder Name 1</h2>
    <div class="options">
      <h5>Option 1</h5>
      <h5>Option 2</h5>
    </div>
  </div>
  <div class="folder">
    <h2 class="name">Folder Name 2</h2>
    <div class="options">
      <h5>Option 1</h5>
      <h5>Option 2</h5>
    </div>
  </div>

  <div class="folder">
    <h2 class="name">Folder Name Long Name This Is</h2>
    <div class="options">
      <h5>Option 1</h5>
      <h5>Option 2</h5>
    </div>
  </div>
</div>
  • 1
    Right side of a folder tag needs a bezier curve. Also the shadow needs to be droped via filter, otherwise the `::before` misses it (or needs its own which will overlap with the parent's shadow). – Jared Mar 20 '22 at 20:41