22

I am currently attempting to generate a 'wavy ghostly bottom' shape. This shape contains two double curves:

Shape with two double curves

Although the bottom part of this image I think portrays it in better imagery.


My Code

My Current Attempt to generate this shape was using pseudo elements and overflow: hidden, although this does not allow for a gradient background (would require a plain background):

Attempt 1 - Using Pseudo Elements with overflow hidden

.bottom {
  height: 300px;
  width: 300px;
  background: lightgray;
  position: relative;
  overflow: hidden;
  margin-top:-150px;
  -webkit-transform:rotate(45deg);
  transform:rotate(45deg);
}
.bottom:before, .bottom:after{
  position: absolute;
  content: "";
  background: white; 
}
.bottom:before {
    height: 150%;
  width: 150%; 
  top: 50%;
  border-radius:50%;
  left: -45%;
}

.bottom:after {
    height: 200%;
  width: 100%; 
  bottom: -40%;
  border-radius:50%;
  left: 90%;
}
<div class="bottom"></div>

Attempt 2 - Using Pseudo Elements with 's' shape

.bottom {
  background: lightgray;
  width: 300px;
  height: 300px;
  position: relative;
  overflow:hidden;
  color:white;
  border-radius:0 100% 0 100%;
}
.bottom:before{
  content:"S";
  position:absolute;
  height:100%;
  width:100%;
  top:-100%;
  left:-75%;
  font-size:60em;
  font-family: 'arial';
  }

.bottom:after{
  content:"S";
  position:absolute;
  height:100%;
  width:100%;
  top:-150%;
  left:-75%;
  font-size:60em;
  font-family: 'arial';
  }
<div class="bottom"></div>

Attempt 3 - extra elements and box shadows

I also have recently tried using box shadows and extra elements (which i would be ok with), but even then, I can't create it properly:

.bottom {
    height:300px;
    width:300px;
    position:relative;
    overflow:hidden;
}
.bottom-left {
    position:absolute;
    top:50%;
    left:-50%;
    height:100%;
    width:100%;
    border-radius:50%;
    box-shadow: inset -35px 35px 0px -24px rgba(50, 50, 50, 1);
    z-index:8;
    background:white;
}
.top {
    position:absolute;
    height:100%;
    top:-35%;
    left:0;
    width:50%;
    border-radius:50%;
    z-index:8;
    background:gray;
    box-shadow:inset 35px -35px 0px -24px rgba(50, 50, 50, 1);
}
.top-right {
    position:absolute;
    top:-80%;
    left:45%;
    height:120%;
    width:100%;
    border-radius:50%;
    box-shadow:inset 35px -35px 0px -24px rgba(50, 50, 50, 1);
    border:20px solid gray;
}
.bigone {
    position:absolute;
    top:0;
    left:-20%;
    height:105%;
    width:100%;
    border-radius:50%;
    box-shadow:inset -35px -35px 0px -24px rgba(50, 50, 50, 1);
    -webkit-transform:rotate(-30deg);
    transform:rotate(-30deg);
    -webkit-transform-origin:center center;
    transform-origin:center center;
    background:gray;
}
<div class="bottom">
    <div class="bottom-left"></div>
    <div class="top"></div>
    <div class="top-right"></div>
    <div class="bigone"></div>
</div>

None of these approaches seem to allow the generation of this double curved shape easily, and would require a 'block coloured background'

Note: I would be reluctant to resort to SVG since I have 90% of the 'overall shape' completed using just pure css, so It would be good/nice to complete this without an svg element


The internal shape would be a block color, but the border isn't compulsory/critical in my design.

this is where I would like to add it to


Update

web-tiki
  • 99,765
  • 32
  • 217
  • 249
jbutler483
  • 24,074
  • 9
  • 92
  • 145
  • 13
    Frankly, I doubt if this is possible with CSS (at least not without multiple elements)...SVG would be the way I'd go. – Paulie_D Mar 11 '15 at 12:05
  • Why don't you use Photoshop or some other program? You are really confusing me, because CSS is obviously not meant for that. – Gintoki Mar 11 '15 at 12:07
  • 7
    While CSS *may* not be the correct tool I'm curious to see what the internet comes up with, when asked to produce a 'ghostly bottom.' – David Thomas Mar 11 '15 at 12:10
  • @Paulie_D: I wouldn't mind using another element, But nothing's impossible :P – jbutler483 Mar 11 '15 at 12:11
  • @DavidThomas: I had to laugh at that, but I really don't think there's exactly a 'defined name' for it. A wobbly triangle, perhaps? – jbutler483 Mar 11 '15 at 12:12
  • 2
    Check out this great link of [css shapes](https://css-tricks.com/examples/ShapesOfCSS/) I don't think there is in there a shape like the one you are asking for, but definitly you can look at the techniques to make pure css complex shapes. Hope that this helps you – Yerko Palma Mar 11 '15 at 12:41
  • Can you specify a particular case where you need to use this on your website? – Mr. Alien Mar 11 '15 at 13:48
  • I like to point out that you can start learning svg and use svg paths. see the best tutorial on svg (fotr). Bye the way i was just joking! good question! – Max Payne Mar 11 '15 at 13:54
  • @Mr.Alien: [here](http://butlers-web.co.uk/Home/dfgdfgfd) (note: not finished by any means) - purely testing/constructing at moment! – jbutler483 Mar 11 '15 at 14:15
  • 1
    @jbutler483 that is not the reason to use CSS for making such weird shapes – Mr. Alien Mar 11 '15 at 14:43
  • @Mr.Alien: I never said it was :P I just haven't got round to fully understanding svg, and I've found css easier to animate because of this. – jbutler483 Mar 11 '15 at 14:45
  • 1
    @jbutler483 i would call this a "genie effect". apple uses this term to describe the "minimize to dock" animation, and this looks similar. – user428517 Mar 11 '15 at 18:41
  • 1
    Wow and I thought I was a purist for creating angled fading background shadows in pure CSS. – Chloe Mar 11 '15 at 21:37

2 Answers2

31

Considering :

  • the amount of code needed
  • the hassle of aligning double curves

CSS doesn't seem to be the way to go here and SVG way more appropriate. To illustrate, see these two snippets :

SVG

DEMO

/*** FOR THE DEMO **/
svg{
    display:block;
    width:70%;
    margin:0 auto;
    opacity:0.8;
}
body{
    background: url('http://lorempixel.com/output/people-q-g-640-480-7.jpg');
    background-size:cover;
}
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 100 80">
    <path stroke-width="1" stroke="#000" fill="grey" d="M95 5 Q70 20 70 38 T50 65 Q55 50 30 40 T5 5z"/>
</svg>

CSS

DEMO (consider I only made one double curve on the right side of the shape)

.ghost {
  position: relative;
  width: 400px;
  height: 300px;
  margin: 0 auto;
  overflow: hidden;
}
.ghost:before,
.ghost:after {
  content: '';
  position: absolute;
}
.ghost:before {
  bottom: 0;
  right: 50%;
  width: 70%;
  height: 30%;
  transform-origin: 100% 100%;
  transform: skewY(30deg) rotate(20deg);
  box-shadow: -100px -100px 0px 99px #656565;
  border-top-right-radius: 30% 100%;
}
.ghost:after {
  top: 0;
  right: 0;
  transform-origin: 100% 0;
  transform: skewX(-10deg) rotate(-20deg);
  box-shadow: none;
  height: 107px;
  width: 173px;
  border-top-left-radius: 90% 100%;
  box-shadow: -30px -30px 0px 29px #656565, 60px -110px 0px 109px #656565;
}
<div class="ghost">
</div>

Note that I didn't list out the advantages of using an svg in this case (responsiveness, quality of output, curve control, border, border color/opacity, fill colour/opacity, transparency, maintainability, amount of time to build the shape...)

web-tiki
  • 99,765
  • 32
  • 217
  • 249
23

You should use boxshadows and overflows to make that shape.

body {background:url('http://whofortedblog.com/wp-content/uploads/2013/01/33c9f33218a6cab6054375fb76129a80.jpeg');
background-size: cover;}
div {
  height: 100px;
  width: 200px;
  overflow: hidden;
  position: relative;
  -webkit-transform: scale(1,1.1);
  -moz-transform: scale(1,1.1);
  -ms-transform: scale(1,1.1);
  -o-transform: scale(1,1.1);
  transform: scale(1,1.1);
}
div:before {
  height: 80px;
  width: 100px;
  border-radius: 50% / 50%;
  box-shadow: 40px -11px 0 -20px white, 42px -22px 0 -10px white, 50px -28px 0 -8px white, 36px -95px 0 20px white;
  content: "";
  position: absolute;
  -webkit-transform: scale(0.9,1.1);
  -moz-transform: scale(0.9,1.1);
  -ms-transform: scale(0.9,1.1);
  -o-transform: scale(0.9,1.1);
  transform: scale(0.9,1.1);
  top: 50%;
  left: -10px;
}
div:after {
  height: 70px;
  width: 120px;
  border-radius: 50%;
  -webkit-transform: rotate(-35deg);
  -moz-transform: rotate(-35deg);
  -ms-transform: rotate(-35deg);
  -o-transform: rotate(-35deg);
  transform: rotate(-35deg);
  box-shadow: ;
  content: "";
  position: absolute;
  top: -1%;
  box-shadow: -1px -28px 0 5px white;
  right: -35px;
}
<div></div>

You can certainly improve this version using good position values! In any case, you should almost never use this solution. the best option in my opinion would be a png image or SVG.

Working:

div {
  height: 100px;
  width: 200px;
  overflow: hidden;
  position: relative;
  border: 1px solid black;
}
div:before {
  height: 80px;
  width: 100px;
  border-radius: 50% / 50%;
  background-color: red;
  box-shadow: 40px -9px 0 -20px blue, 42px -20px 0 -10px pink, 50px -25px 0 -8px plum, 37px -95px 0 20px green;
  content: "";
  position: absolute;
  top: 50%;
  left: -10px;
}
div:after {
  height: 70px;
  width: 120px;
  border-radius: 50%;
  background-color: rgba(255, 215, 0, 0.6);
  -webkot-transform: rotate(-35deg);
  -moz-transform: rotate(-35deg);
  -o-transform: rotate(-35deg);
  -ms-transform: rotate(-35deg);
  transform: rotate(-35deg);
  box-shadow: ;
  content: "";
  position: absolute;
  top: -1%;
  box-shadow: -4px -27px 0 5px rgba(0, 255, 215, 0.6);
  right: -44px;
}
<div></div>
Max Payne
  • 2,423
  • 17
  • 32
  • 4
    what happen? in the morning this answer was different, now i looks like a screamer – ViROscar Mar 11 '15 at 22:48
  • @ViROscar It is still working, it just has a background. The shape is in the top left. I would say SVG is probably the way to go as others have mentioned. Just as a note, the CSS version seems ok sometimes but as I scroll it can be buggy in my browser (Firefox). The SVG version displays perfectly without any issues. – Goblinlord Mar 12 '15 at 02:33
  • does'nt it look scary? :) @Goblinlord how do you scroll/ it is not big shape it is a small shape in corner so scrollbar dont appear. but you are right svg is the corect tool for this job. – Max Payne Mar 12 '15 at 03:51
  • @TimKrul I just meant as I scroll through this page with it showing here actually. – Goblinlord Mar 12 '15 at 03:52
  • @Goblinlord i am sorry i wondered how you scroll. :) also many bowsers dont support transforms css : http://www.w3schools.com/css/css3_2dtransforms.asp – Max Payne Mar 12 '15 at 03:59
  • @TimKrul It does the same thing if I scroll using the scroll bar, mouse wheel, center mouse button, or page up/down keys. – Goblinlord Mar 12 '15 at 04:14
  • thank you @Goblinlord :) i use ie8 and this is not working. i also try google chrome and it works in it. – Max Payne Mar 12 '15 at 04:16
  • i've tried the code snippet and is working with ie9, the current version of chrome and firefox 35. however, running firefox in a virtual pc cause problems with the scroll (at least in my case, for me, it doesn't have any sense). – ViROscar Mar 12 '15 at 14:31
  • @ViROscar thank you very much for reporting. can you plese take a photo of error. – Max Payne Mar 13 '15 at 12:55