← Mike Higgins Home
Custom Code Experiment •

CSS Spider

Source Code View HTML / CSS / JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title></title>
<style>
* {
  margin: 0;
  padding: 0;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

html, body {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

body {
  background: linear-gradient(-45deg, #ff69b4, #ff1493, #ffb6c1, #ff69b4);
  background-size: 400% 400%;
  animation: gradient 15s ease infinite;
  position: relative;
  touch-action: none;
  display: flex;
  justify-content: center;
  align-items: center;
}

@keyframes gradient {
  0% {
    background-position: 0% 50%;
  }
  50% {
    background-position: 100% 50%;
  }
  100% {
    background-position: 0% 50%;
  }
}

.spider-container {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

.spider {
  position: relative;
  display: block;
  animation: swing 2s infinite ease-in-out;
  transform-origin: top center;
}

.spiderweb {
  width: 2px;
  height: 200px;
  margin: 0 auto;
  background: linear-gradient(to bottom, rgba(255,255,255,0.8) 0%, rgba(255,255,255,0.2) 100%);
  box-shadow: 0 0 10px rgba(255,255,255,0.5);
}

.body {
  width: 100px;
  height: 80px;
  position: relative;
  border-radius: 50%;
  background-color: #000;
  box-shadow:
    0 5px 15px rgba(0,0,0,0.5),
    inset 0 2px 5px rgba(255,255,255,0.1);
}

.eye {
  width: 33.33px;
  height: 33.33px;
  position: absolute;
  bottom: 20px;
  background-color: white;
  border-radius: 50%;
  box-shadow: 0 0 10px rgba(255,255,255,0.8);
}

.eye:after {
  width: 10px;
  height: 10px;
  content: "";
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #000;
  border-radius: 50%;
  animation: look 3s infinite ease-in-out;
  box-shadow: 0 0 5px rgba(0,0,0,0.5);
}

.eye.left {
  left: 14.29px;
}

.eye.right {
  right: 14.29px;
}

.legs {
  position: absolute;
  bottom: -10%;
  z-index: -1;
}

.legs.left {
  left: -70%;
}

.legs.right {
  right: -60%;
}

.leg {
  width: 80px;
  height: 40px;
  margin-top: -20px;
  border: 5px solid transparent;
  border-top-color: #000;
  border-radius: 50%/40px 40px 0 0;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.5));
}

.legs.left .leg:nth-child(1) {
  transform: rotate(10deg);
  margin-left: 10px;
}

.legs.left .leg:nth-child(2) {
  transform: rotate(-20deg);
  margin-left: 20px;
}

.legs.left .leg:nth-child(3) {
  transform: rotate(-50deg);
  margin-left: 30px;
}

.legs.right .leg:nth-child(1) {
  transform: rotate(-10deg);
  margin-left: -10px;
}

.legs.right .leg:nth-child(2) {
  transform: rotate(20deg);
  margin-left: -20px;
}

.legs.right .leg:nth-child(3) {
  transform: rotate(50deg);
  margin-left: -30px;
}

@keyframes swing {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-15px);
  }
  100% {
    transform: translateY(0);
  }
}

@keyframes look {
  0%, 40% {
    transform: translate(-50%, -50%);
  }
  45%, 55% {
    transform: translate(-90%, -50%);
  }
  60%, 100% {
    transform: translate(-50%, -50%);
  }
}

@media (max-width: 768px) {
  .body {
    width: 80px;
    height: 64px;
  }

  .spiderweb {
    height: 160px;
  }

  .eye {
    width: 26.67px;
    height: 26.67px;
    bottom: 16px;
  }

  .eye.left {
    left: 11.43px;
  }

  .eye.right {
    right: 11.43px;
  }

  .leg {
    width: 64px;
    height: 32px;
    margin-top: -16px;
    border-width: 4px;
  }

  .legs.left .leg:nth-child(1) {
    margin-left: 8px;
  }

  .legs.left .leg:nth-child(2) {
    margin-left: 16px;
  }

  .legs.left .leg:nth-child(3) {
    margin-left: 24px;
  }

  .legs.right .leg:nth-child(1) {
    margin-left: -8px;
  }

  .legs.right .leg:nth-child(2) {
    margin-left: -16px;
  }

  .legs.right .leg:nth-child(3) {
    margin-left: -24px;
  }

  @keyframes swing {
    0% {
      transform: translateY(0);
    }
    50% {
      transform: translateY(-10px);
    }
    100% {
      transform: translateY(0);
    }
  }
}
</style>
</head>
<body>
<div class="spider-container">
  <div class="spider">
    <div class="spiderweb"></div>
    <div class="body">
      <div class="eye left"></div>
      <div class="eye right"></div>
    </div>
    <div class="legs left">
      <div class="leg"></div>
      <div class="leg"></div>
      <div class="leg"></div>
    </div>
    <div class="legs right">
      <div class="leg"></div>
      <div class="leg"></div>
      <div class="leg"></div>
    </div>
  </div>
</div>

<script>

document.addEventListener('visibilitychange', function() {
  if (!document.hidden) {

    const spider = document.querySelector('.spider');
    const eyes = document.querySelectorAll('.eye');

    spider.style.animation = 'none';
    eyes.forEach(eye => eye.style.animation = 'none');

    void spider.offsetWidth;

    spider.style.animation = '';
    eyes.forEach(eye => eye.style.animation = '');
  }
});

window.addEventListener('load', function() {
  const spider = document.querySelector('.spider');
  spider.style.animation = 'swing 2s infinite ease-in-out';

  setTimeout(() => {
    void spider.offsetWidth;
  }, 10);
});

window.addEventListener('pageshow', function(event) {
  if (event.persisted) {
    const spider = document.querySelector('.spider');
    const eyes = document.querySelectorAll('.eye');

    spider.style.animation = 'none';
    eyes.forEach(eye => eye.style.animation = 'none');

    setTimeout(() => {
      spider.style.animation = '';
      eyes.forEach(eye => eye.style.animation = '');
    }, 50);
  }
});
</script>
</body>
</html>