<div class="phone">
  <div class="phone__screen">
    <div class="demo__top">
      <p class="demo__text">Pull down content part</p>
      <p class="demo__text half">Activities</p>
      <p class="demo__text half">Saved</p>
      <svg class="demo__svg" viewBox="0 0 375 37">
        <path class="demo__svg__line" stroke-width="3" fill="none" d="M0,1 187,1 a18,18 0 0,1 0,36 a18,18 0 0,1 -12.6,-30.6"/>
        <path class="demo__svg__smile" stroke-width="3" fill="none" d="M176.61,25 Q187,14 197.39,25" />
      </svg>
    </div>
    <div class="demo__body">
      <svg class="demo__svg-bg" viewBox="0 0 375 667" preserveAspectRatio="xMaxYMin slice">
        <path class="demo__svg-bg__path" d="M0,0 C125,0 250,0 375,0 S375,0 375,0 L375,667 0,667z" />
      </svg>
      <div class="demo__content">
        <div class="demo__el"></div>
        <div class="demo__el"></div>
        <div class="demo__el"></div>
      </div>
    </div>
  </div>
</div>
*, *:before, *:after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}
html, body {
  font-size: 62.5%;
  
  @media (max-width: 320px) {
    font-size: 45%;
  }
}
body {
  background: #393A56;
}

$screenW: 37.5rem;
$screenH: 66.7rem;
$padSide: 2.4rem;
$padVert: 10.6rem;
$phoneW: $screenW + $padSide*2;
$phoneH: $screenH + $padVert*2;
$phoneBorderW: 0.4rem;
$topH: 9rem;

$lineColor: #4EDDC8;

$totalLen: 285.53px;
$lineLen: 187px;
$circleLen: $totalLen - $lineLen;

$resetAT: 0.5s;
$releaseStep1AT: 0.5s;
$releaseStep2AT: 0.3s;

.phone {
  position: relative;
  width: $phoneW;
  height: $phoneH;
  padding: $padVert - $phoneBorderW $padSide - $phoneBorderW;
  margin: 3rem auto 3rem;
  background: #000000;
  border-radius: 5.6rem;
  border: $phoneBorderW solid #B5B5B5;
  
  @media (max-width: 320px) {
    width: 100%;
    height: auto;
    margin: 0 auto;
    padding: 0;
    border-radius: 0;
    border: 0;
    background: transparent;
  } 

  &__screen {
    overflow: hidden;
    position: relative;
    width: $screenW;
    height: $screenH;
    background: #39425A;
    
    @media (max-width: 320px) {
      width: 100%;
      height: auto;
    }
  }
}

.demo {
  position: relative;
  height: 100%;

  &__top {
    position: relative;
    height: $topH;
    padding-top: 3rem;
    text-align: center;
    font-size: 0;
    color: #CECED6;
    text-transform: uppercase;
  }

  &__text {
    font-size: 1.2rem;
    margin-bottom: 1.6rem;

    &.half {
      display: inline-block;
      vertical-align: top;
      width: 50%;
    }
  }

  &__body {
    position: relative;
    min-height: $screenH;
    padding: 1.5rem;
    transform: translate3d(0,0,0);
    user-select: none;

    &.reset {
      transition: transform $resetAT;
      transform: translate3d(0,0,0) !important;
    }

    &.waiting {
      transition: transform $releaseStep2AT;
      transform: translate3d(0,5rem,0) !important;
    }
    
    @media (max-width: 320px) {
      height: 500px;
      padding: 0;
    }
  }

  &__svg-bg {
    overflow: visible;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    
    @media (max-width: 320px) {
      height: 390px;
    }

    &__path {
      fill: #FAFAFB;
      stroke: transparent;
    }
  }

  &__content {

    &.reset {
      transition: transform $resetAT;
      transform: translate3d(0,0,0) !important;
    }
  }

  &__el {
    position: relative;
    height: 16rem;
    margin-bottom: 2rem;
    background: #ffffff;

    &:before {
      content: "";
      position: absolute;
      left: 1.5rem;
      top: 1.5rem;
      width: 9rem;
      height: 9rem;
      border-radius: 1.5rem;
      background: #5A534F;
      
      @media (max-width: 320px) {
        left: 4.5rem;
      }
    }

    &:after {
      content: "";
      position: absolute;
      left: 12rem;
      top: 1.5rem;
      width: $screenW - 16.5rem;
      height: 1.5rem;
      border-radius: 0.7rem;
      background: #5A534F;
      color: #5A534F;
      box-shadow: 0 3rem, 0 6rem;
      
      @media (max-width: 320px) {
        left: 16rem;
        width: 24rem;
      }
    }
  }

  &__svg {
    overflow: visible;
    position: absolute;
    left: 0;
    top: $topH - 0.3rem;
    width: 100%;
    height: 3.7rem;

    &__line {
      stroke: $lineColor;
      stroke-dashoffset: $circleLen;
      stroke-dasharray: $totalLen, $totalLen;
      transform-origin: 187px 19px;

      &.show-circle {
        transition: stroke-dashoffset $releaseStep1AT*0.65;
        stroke-dashoffset: -$lineLen !important;
      }

      &.rotating {
        animation: rotating 0.5s infinite linear;
      }

      &.reset {
        transition: stroke-dashoffset $resetAT;
        stroke-dashoffset: $circleLen !important;
        transform: rotate(0);
      }
    }

    &__smile {
      stroke: $lineColor;
      stroke-dashoffset: 30px;
      stroke-dasharray: 30px, 30px;
      transform-origin: 187px 19px;
      opacity: 0;
      transition: opacity 0.1s, stroke-dashoffset 0.5s;
      transition-delay: 0.2s;
      transform: rotate(0);

      &.active {
        opacity: 1;
        stroke-dashoffset: 0;
      }

      &.minified {
        transition: stroke-dashoffset 0.5s 0.85s, opacity 0.1s 1.25s;
        stroke-dashoffset: 25px;
        opacity: 0;
        animation: rotating 0.5s 0.35s infinite linear;
      }
    }
  }
}

@keyframes rotating {
  to {
    transform: rotate(360deg);
  }
}
View Compiled
$(document).ready(function() {

  var animating = false;

  var $body = $(".demo__body");
  var $content = $(".demo__content");
  var $line = $(".demo__svg__line");
  var $smile = $(".demo__svg__smile");
  var $bgPath = $(".demo__svg-bg__path");

  var resetD = "M0,0 C125,0 250,0 375,0 S375,0 375,0 L375,667 0,667z";
  var smileInit = "M176.61,25 Q187,19 197.39,25";
  var smileMid = "M176.61,25 Q187,25 197.39,25";
  var smileEnd = "M176.61,25 Q187,34 197.39,25";

  var totalLen = $line[0].getTotalLength();
  var upperLen = 187;
  var circleLen = totalLen - upperLen;
  var minLineLen = 60;
  var lineDragBoundries = upperLen - minLineLen;

  var pullDeltaY = 0;
  var pullSlowCoef = 1.2;
  var maxPullY = 150;
  var minReleaseY = 120;
  var contentYCoef = 0.4;
  var maxContentY = maxPullY*contentYCoef;
  var bodyOffsetX = 0;
  var bodyW = $body.outerWidth();

  var resetAT = 500;
  var releaseStep1AT = 800;
  var releaseWaitTime = 3000;

  var easings = {
    elastic: function(t,b,c,d) {
      var ts = (t/=d)*t;
      var tc = ts*t;
      return b+c*(33*tc*ts + -106*ts*ts + 126*tc + -67*ts + 15*t);
    },
    inCubic: function(t,b,c,d) {
      var tc = (t/=d)*t*t;
      return b+c*(tc);
    }
  };

  function SvgAddClass(el, cl) {
    var regEx = new RegExp('(?:^|\\s)'+cl+'(?!\\S)', "gi");
    if (regEx.test(el.attr("class"))) return;
    el.attr("class", el.attr("class") + " " + cl);
  };

  function SvgRemoveClass(el, cl) {
    var regEx = new RegExp('(?:^|\\s)'+cl+'(?!\\S)', "gi");
    el.attr("class", el.attr("class").replace(regEx, ""));
  };

  function SvgPathTween(from, to, time, easing) {
    var regex = /\d+(\.\d{1,2})?/g;
    var fromD = from.attr("d");
    var fm = fromD.match(regex);
    var tm = to.match(regex);
    var diff = [];
    for (var i = 0; i < fm.length; i++) {
      diff.push(+fm[i] - (+tm[i]));
    }
    var time = time || 1600;
    var curFrame = 0;
    var frames = time / 1000 * 60;
    var easing = easing || "elastic";

    function animate() {
      if (curFrame > frames) return;
      var i = 0;
      var newD = fromD.replace(regex, function(m) {
        if (+m === 0 || // if nothing changed - skip
            i % 2 === 0) { // in this demo I want to animate only y values
          i++;
          return m;
        }
        return +easings[easing](curFrame, +fm[i], 0 - diff[i++], frames).toFixed(2);
      });
      from.attr("d", newD);
      curFrame++;
      requestAnimationFrame(animate);
    };

    animate();
  };

  function pullChange(y, x) {
    var pullY = (y <= maxPullY) ? y : maxPullY;
    if (pullY < 0) pullY = 0;
    var pullCoef = pullY / maxPullY;
    var sdo = circleLen + pullCoef * lineDragBoundries;
    var pullYCont = +(pullY*contentYCoef).toFixed(2);
    var bodyX = parseInt(x - bodyOffsetX, 10);
    if (bodyX < 0) bodyX = 0;
    if (bodyX > bodyW) bodyX = bodyW;
    var leftX = bodyX - 50;
    if (leftX < 0) leftX = 0;
    var rightX = bodyX + 50;
    if (rightX > bodyW) rightX = bodyW;

    $body.css("transform", "translate3d(0,"+ pullY +"px,0)");
    $content.css("transform", "translate3d(0,"+ pullYCont +"px,0)");
    $line.css("stroke-dashoffset", sdo);

    $bgPath.attr("d", "M0,0 C"+(leftX-25)+",0 "+(leftX)+","+pullYCont+" "+bodyX+","+pullYCont+" S"+(rightX+25)+",0 375,0 L375,667 0,667z");
  };

  function reset() {
    $body.addClass("reset");
    $content.addClass("reset");
    SvgAddClass($line, "reset");
    SvgPathTween($bgPath, resetD);

    setTimeout(function() {
      $body.removeClass("reset").attr("style", "");
      $content.removeClass("reset").attr("style", "");
      SvgRemoveClass($line, "reset");
      $line.attr("style", "");
      animating = false;
    }, resetAT);
  };

  function performMagic() {
    $body.addClass("waiting");
    SvgAddClass($line, "show-circle");
    SvgPathTween($bgPath, resetD);
    $content.addClass("reset");

    setTimeout(function() {
      SvgAddClass($line, "rotating");
    }, releaseStep1AT*0.32);

    setTimeout(function() {
      $content.removeClass("reset").attr("style", "");
      
      SvgAddClass($smile, "active");
      
      setTimeout(function() {
        SvgPathTween($smile, smileMid, 300, "inCubic");
        
        setTimeout(function() {
          SvgPathTween($smile, smileEnd, 300, "inCubic");
          
          SvgAddClass($smile, "minified");
        }, 500);
      }, 700);
      
    }, resetAT);

    setTimeout(function() {
      SvgRemoveClass($line, "rotating");
      SvgRemoveClass($line, "show-circle");
      SvgAddClass($line, "reset");
      $body.removeClass("waiting").addClass("reset");

      setTimeout(function() {
        $body.removeClass("reset").attr("style", "");
        SvgRemoveClass($line, "reset");
        $line.attr("style", "");
        SvgRemoveClass($smile, "minified");
        SvgRemoveClass($smile, "active");
        SvgPathTween($smile, smileInit, 50, "inCubic");
        animating = false;
      }, resetAT);

    }, releaseWaitTime);

  };

  function release() {
    animating = true;
    if (pullDeltaY < minReleaseY) {
      reset();
    } else {
      performMagic();
    }
  };

  $(document).on("mousedown touchstart", ".demo__body", function(e) {
    if (animating) return;
    var startY =  e.pageY || e.originalEvent.touches[0].pageY;
    bodyOffsetX = $body.offset().left;

    $(document).on("mousemove touchmove", function(e) {
      var y = e.pageY || e.originalEvent.touches[0].pageY;
      var x = e.pageX || e.originalEvent.touches[0].pageX;
      pullDeltaY = (y - startY) / pullSlowCoef;
      if (!pullDeltaY) return;
      pullChange(pullDeltaY, x);
    });

    $(document).on("mouseup touchend", function() {
      $(document).off("mousemove touchmove mouseup touchend");
      if (!pullDeltaY) return;
      release();
    });
  });

});
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js