본문 바로가기

Navigation Page Design (네비게이션 페이지 디자인)

반응형
더보기

CSS

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: "ROBOTO", sans-serif;
}

.nav,
.slider {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
  position: relative;
  background-color: #1e1f26;
  text-align: center;
  padding: 0 2em;
}

.nav h1,
.slider h1 {
  font-family: "Josefin Sans", sans-serif;
  font-size: 5vw;
  margin: 0;
  padding-bottom: 0.5rem;
  letter-spacing: 0.5rem;
  color: #03dac6;
  transition: all 0.3s ease;
  z-index: 3;
}
h1:hover {
  transform: translate3d(0, -10px, 22px);
  color: #ff0266;
}

.slider h2 {
  font-size: 2vw;
  letter-spacing: 0.3rem;
  font-family: "ROBOTO", sans-serif;
  font-weight: 300;
  color: #faebd7;
  z-index: 4;
}
h3.span {
  font-size: 2vw;
  letter-spacing: 0.7em;
  font-family: "ROBOTO", sans-serif;
  font-weight: 300;
  color: #faebd7;
  z-index: 4;
}
span:hover {
  color: #ff0266;
  font-weight: 500;
  font-size: 2.2vw;
}

a {
  text-decoration: none;
}

.nav-container {
  display: flex;
  flex-direction: row;
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 75px;
  box-shadow: 20px 20px 50px rgba(0, 0, 0, 0.5);
  background: #1e1f26;
  z-index: 10;
  transition: all 0.3s cubic-bezier(0.19, 1, 0.22, 1);
}

.nav-container--top-first {
  position: fixed;
  top: 75px;
  transition: all 0.3s cubic-bezier(0.19, 1, 0.22, 1);
}

.nav-container--top-second {
  position: fixed;
  top: 0;
}
.nav-tab {
  display: flex;
  justify-content: center;
  align-items: center;
  flex: 1;
  color: #03dac6;
  letter-spacing: 0.1rem;
  transition: all 0.5s ease;
  font-size: 2vw;
}

.nav-tab:hover {
  color: #1e1f26;
  background: #03dac6;
  transition: all 0.5s ease;
}

.nav-tab-slider {
  position: absolute;
  bottom: 0;
  width: 0;
  height: 2px;
  background: #03dac6;
  transition: left 0.3s ease;
}
.background {
  position: absolute;
  height: 90vh;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: auto;
}
@media (min-width: 800px) {
  .nav h1,
  .slider h1 {
    font-size: 5vw;
  }

  .nav h2,
  .slider h2 {
    font-size: 3vw;
  }

  .nav-tab {
    font-size: 3vw;
  }
}

@media screen only (min-width: 360px) {
  .nav h1,
  .slider h1 {
    font-size: 8vw;
  }

  .nav h2,
  .slider h2 {
    font-size: 2vw;
    letter-spacing: 0.2vw;
  }

  .nav-tab {
    font-size: 1.2vw;
  }
}
.background {
  position: absolute;
  height: 100vh;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 0;
}
.loader span {
  color: #faebd7;
  text-shadow: 0 0 0 #faebd7;
  -webkit-animation: loading 1s ease-in-out infinite alternate;
}

@-webkit-keyframes loading {
  to {
    text-shadow: 20px 0 70px #ff0266;
    color: #ff0266;
  }
}
.loader span:nth-child(2) {
  -webkit-animation-delay: 0.1s;
}
.loader span:nth-child(3) {
  -webkit-animation-delay: 0.2s;
}
.loader span:nth-child(4) {
  -webkit-animation-delay: 0.3s;
}
.loader span:nth-child(5) {
  -webkit-animation-delay: 0.4s;
}
.loader span:nth-child(6) {
  -webkit-animation-delay: 0.5s;
}
.loader span:nth-child(7) {
  -webkit-animation-delay: 0.6s;
}
.loader span:nth-child(8) {
  -webkit-animation-delay: 0.7s;
}
.loader span:nth-child(9) {
  -webkit-animation-delay: 0.8s;
}

.loader span:nth-child(10) {
  -webkit-animation-delay: 0.9s;
}
.loader span:nth-child(11) {
  -webkit-animation-delay: 1s;
}
.loader span:nth-child(12) {
  -webkit-animation-delay: 1.1s;
}
.loader span:nth-child(13) {
  -webkit-animation-delay: 1.2s;
}
.loader span:nth-child(14) {
  -webkit-animation-delay: 1.3s;
}
.loader span:nth-child(15) {
  -webkit-animation-delay: 1.4s;
}
.loader span:nth-child(16) {
  -webkit-animation-delay: 1.5s;
}
.loader span:nth-child(17) {
  -webkit-animation-delay: 1.6s;
}
.loader span:nth-child(18) {
  -webkit-animation-delay: 1.7s;
}
.loader span:nth-child(19) {
  -webkit-animation-delay: 1.8s;
}
.loader span:nth-child(20) {
  -webkit-animation-delay: 1.9s;
}
.loader span:nth-child(21) {
  -webkit-animation-delay: 2s;
}
.loader span:nth-child(22) {
  -webkit-animation-delay: 2.1s;
}

HTML

<sectio class="nav">
  <h1>FRONTEND TRENDS</h1>
  <h3 class="span loader"><span class="m">B</span><span class="m">E</span><span class="m">N</span><span class="m">E</span><span class="m">F</span><span class="m">I</span><span class="m">T</span><span class="m">S</span><span class="m">&nbsp;</span><span class="m">o</span><span class="m">f</span><span class="m">&nbsp;</span><span class="m">T</span><span class="m">E</span><span class="m">C</span><span class="m">H</span><span class="m">N</span><span class="m">O</span><span class="m">L</span><span class="m">O</span><span class="m">G</span><span class="m">I</span><span class="m">E</span><span class="m">S</span></h3>
  <div class="nav-container"><a class="nav-tab" href="#tab-svelte">SVELTE</a><a class="nav-tab" href="#tab-esbuild">ESBUILD</a><a class="nav-tab" href="#tab-next">NEXT.JS</a><a class="nav-tab" href="#tab-typescript">TYPESCRIPT</a><a class="nav-tab" href="#tab-vite">VITE</a><span class="nav-tab-slider"></span></div>
</sectio>
<main class="main">
  <section class="slider" id="tab-svelte">
    <h1>SVELTE</h1>
    <h2>another frontend JS framework</h2>
  </section>
  <section class="slider" id="tab-esbuild">
    <h1>ESBUILD</h1>
    <h2>an extremely fast JavaScript bundler</h2>
  </section>
  <section class="slider" id="tab-next">
    <h1>NEXT.JS</h1>
    <h2>framework for Production</h2>
  </section>
  <section class="slider" id="tab-typescript">
    <h1>TYPESCRIPT</h1>
    <h2>giving you better tooling at any scale</h2>
  </section>
  <section class="slider" id="tab-vite">
    <h1>VITE</h1>
    <h2>a frontend build tool</h2>
  </section>
</main>
<canvas class="background"></canvas>

SCRIPT

var Particles = (function (e, t) {
    "use strict";
    var n,
        i = {};
    function o(e, t) {
        return e.x < t.x ? -1 : e.x > t.x ? 1 : e.y < t.y ? -1 : e.y > t.y ? 1 : 0;
    }
    return (
        ((n = (function () {
            return function () {
                var e = this;
                (e.defaults = { responsive: null, selector: null, maxParticles: 100, sizeVariations: 3, showParticles: !0, speed: 0.5, color: "#000000", minDistance: 120, connectParticles: !1 }),
                    (e.element = null),
                    (e.context = null),
                    (e.ratio = null),
                    (e.breakpoints = []),
                    (e.activeBreakpoint = null),
                    (e.breakpointSettings = []),
                    (e.originalSettings = null),
                    (e.storage = []),
                    (e.usingPolyfill = !1);
            };
        })()).prototype.init = function (e) {
            var t = this;
            return (
                (t.options = t._extend(t.defaults, e)),
                (t.originalSettings = JSON.parse(JSON.stringify(t.options))),
                (t._animate = t._animate.bind(t)),
                t._initializeCanvas(),
                t._initializeEvents(),
                t._registerBreakpoints(),
                t._checkResponsive(),
                t._initializeStorage(),
                t._animate(),
                t
            );
        }),
        (n.prototype.destroy = function () {
            var t = this;
            (t.storage = []), t.element.remove(), e.removeEventListener("resize", t.listener, !1), e.clearTimeout(t._animation), cancelAnimationFrame(t._animation);
        }),
        (n.prototype._initializeCanvas = function () {
            var n,
                i,
                o = this;
            if (!o.options.selector) return console.warn("particles.js: No selector specified! Check https://github.com/marcbruederlin/particles.js#options"), !1;
            (o.element = t.querySelector(o.options.selector)),
                (o.context = o.element.getContext("2d")),
                (n = e.devicePixelRatio || 1),
                (i = o.context.webkitBackingStorePixelRatio || o.context.mozBackingStorePixelRatio || o.context.msBackingStorePixelRatio || o.context.oBackingStorePixelRatio || o.context.backingStorePixelRatio || 1),
                (o.ratio = n / i),
                (o.element.width = o.element.offsetParent ? o.element.offsetParent.clientWidth * o.ratio : o.element.clientWidth * o.ratio),
                o.element.offsetParent && "BODY" === o.element.offsetParent.nodeName
                    ? (o.element.height = e.innerHeight * o.ratio)
                    : (o.element.height = o.element.offsetParent ? o.element.offsetParent.clientHeight * o.ratio : o.element.clientHeight * o.ratio),
                (o.element.style.width = "100%"),
                (o.element.style.height = "100%"),
                o.context.scale(o.ratio, o.ratio);
        }),
        (n.prototype._initializeEvents = function () {
            var t = this;
            (t.listener = function () {
                t._resize();
            }.bind(this)),
                e.addEventListener("resize", t.listener, !1);
        }),
        (n.prototype._initializeStorage = function () {
            var e = this;
            e.storage = [];
            for (var t = e.options.maxParticles; t--; ) e.storage.push(new i(e.context, e.options));
        }),
        (n.prototype._registerBreakpoints = function () {
            var e,
                t,
                n,
                i = this,
                o = i.options.responsive || null;
            if ("object" == typeof o && null !== o && o.length) {
                for (e in o)
                    if (((n = i.breakpoints.length - 1), (t = o[e].breakpoint), o.hasOwnProperty(e))) {
                        for (; n >= 0; ) i.breakpoints[n] && i.breakpoints[n] === t && i.breakpoints.splice(n, 1), n--;
                        i.breakpoints.push(t), (i.breakpointSettings[t] = o[e].options);
                    }
                i.breakpoints.sort(function (e, t) {
                    return t - e;
                });
            }
        }),
        (n.prototype._checkResponsive = function () {
            var t,
                n = this,
                i = !1,
                o = e.innerWidth;
            if (n.options.responsive && n.options.responsive.length && null !== n.options.responsive) {
                for (t in ((i = null), n.breakpoints)) n.breakpoints.hasOwnProperty(t) && o <= n.breakpoints[t] && (i = n.breakpoints[t]);
                null !== i
                    ? ((n.activeBreakpoint = i), (n.options = n._extend(n.options, n.breakpointSettings[i])))
                    : null !== n.activeBreakpoint && ((n.activeBreakpoint = null), (i = null), (n.options = n._extend(n.options, n.originalSettings)));
            }
        }),
        (n.prototype._refresh = function () {
            this._initializeStorage(), this._draw();
        }),
        (n.prototype._resize = function () {
            var t = this;
            (t.element.width = t.element.offsetParent ? t.element.offsetParent.clientWidth * t.ratio : t.element.clientWidth * t.ratio),
                t.element.offsetParent && "BODY" === t.element.offsetParent.nodeName
                    ? (t.element.height = e.innerHeight * t.ratio)
                    : (t.element.height = t.element.offsetParent ? t.element.offsetParent.clientHeight * t.ratio : t.element.clientHeight * t.ratio),
                t.context.scale(t.ratio, t.ratio),
                clearTimeout(t.windowDelay),
                (t.windowDelay = e.setTimeout(function () {
                    t._checkResponsive(), t._refresh();
                }, 50));
        }),
        (n.prototype._animate = function () {
            var t = this;
            t._draw(), (t._animation = e.requestAnimFrame(t._animate));
        }),
        (n.prototype.resumeAnimation = function () {
            this._animation || this._animate();
        }),
        (n.prototype.pauseAnimation = function () {
            var t = this;
            if (t._animation) {
                if (t.usingPolyfill) e.clearTimeout(t._animation);
                else (e.cancelAnimationFrame || e.webkitCancelAnimationFrame || e.mozCancelAnimationFrame)(t._animation);
                t._animation = null;
            }
        }),
        (n.prototype._draw = function () {
            var t = this,
                n = t.element,
                i = n.offsetParent ? n.offsetParent.clientWidth : n.clientWidth,
                r = n.offsetParent ? n.offsetParent.clientHeight : n.clientHeight,
                a = t.options.showParticles,
                s = t.storage;
            n.offsetParent && "BODY" === n.offsetParent.nodeName && (r = e.innerHeight), t.context.clearRect(0, 0, n.width, n.height), t.context.beginPath();
            for (var l = s.length; l--; ) {
                var c = s[l];
                a && c._draw(), c._updateCoordinates(i, r);
            }
            t.options.connectParticles && (s.sort(o), t._updateEdges());
        }),
        (n.prototype._updateEdges = function () {
            for (var e = this, t = e.options.minDistance, n = Math.sqrt, i = Math.abs, o = e.storage, r = o.length, a = 0; a < r; a++)
                for (var s = o[a], l = a + 1; l < r; l++) {
                    var c,
                        f = o[l],
                        p = s.x - f.x,
                        h = s.y - f.y;
                    if (((c = n(p * p + h * h)), i(p) > t)) break;
                    c <= t && e._drawEdge(s, f, 1.2 - c / t);
                }
        }),
        (n.prototype._drawEdge = function (e, t, n) {
            var i = this,
                o = i.context.createLinearGradient(e.x, e.y, t.x, t.y),
                r = this._hex2rgb(e.color),
                a = this._hex2rgb(t.color);
            o.addColorStop(0, "rgba(" + r.r + "," + r.g + "," + r.b + "," + n + ")"),
                o.addColorStop(1, "rgba(" + a.r + "," + a.g + "," + a.b + "," + n + ")"),
                i.context.beginPath(),
                (i.context.strokeStyle = o),
                i.context.moveTo(e.x, e.y),
                i.context.lineTo(t.x, t.y),
                i.context.stroke(),
                i.context.fill(),
                i.context.closePath();
        }),
        (n.prototype._extend = function (e, t) {
            return (
                Object.keys(t).forEach(function (n) {
                    e[n] = t[n];
                }),
                e
            );
        }),
        (n.prototype._hex2rgb = function (e) {
            var t = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);
            return t ? { r: parseInt(t[1], 16), g: parseInt(t[2], 16), b: parseInt(t[3], 16) } : null;
        }),
        ((i = function (n, i) {
            var o = this,
                r = Math.random,
                a = i.speed,
                s = i.color instanceof Array ? i.color[Math.floor(Math.random() * i.color.length)] : i.color;
            (o.context = n), (o.options = i);
            var l = t.querySelector(i.selector);
            (o.x = l.offsetParent ? r() * l.offsetParent.clientWidth : r() * l.clientWidth),
                l.offsetParent && "BODY" === l.offsetParent.nodeName ? (o.y = r() * e.innerHeight) : (o.y = l.offsetParent ? r() * l.offsetParent.clientHeight : r() * l.clientHeight),
                (o.vx = r() * a * 2 - a),
                (o.vy = r() * a * 2 - a),
                (o.radius = r() * r() * i.sizeVariations),
                (o.color = s),
                o._draw();
        }).prototype._draw = function () {
            var e = this;
            e.context.save(), e.context.translate(e.x, e.y), e.context.moveTo(0, 0), e.context.beginPath(), e.context.arc(0, 0, e.radius, 0, 2 * Math.PI, !1), (e.context.fillStyle = e.color), e.context.fill(), e.context.restore();
        }),
        (i.prototype._updateCoordinates = function (e, t) {
            var n = this,
                i = n.x + this.vx,
                o = n.y + this.vy,
                r = n.radius;
            i + r > e ? (i = r) : i - r < 0 && (i = e - r), o + r > t ? (o = r) : o - r < 0 && (o = t - r), (n.x = i), (n.y = o);
        }),
        (e.requestAnimFrame = (function () {
            var t = e.requestAnimationFrame || e.webkitRequestAnimationFrame || e.mozRequestAnimationFrame;
            return (
                t ||
                ((this._usingPolyfill = !0),
                function (t) {
                    return e.setTimeout(t, 1e3 / 60);
                })
            );
        })()),
        new n()
    );
})(window, document);
!(function () {
    "use strict";
    "function" == typeof define && define.amd
        ? define("Particles", function () {
              return Particles;
          })
        : "undefined" != typeof module && module.exports
        ? (module.exports = Particles)
        : (window.Particles = Particles);
})();

window.onload = function () {
  Particles.init({
    selector: ".background"
  });
};
const particles = Particles.init({
  selector: ".background",
  color: ["#03dac6", "#ff0266", "#000000"],
  connectParticles: true,
  responsive: [
    {
      breakpoint: 768,
      options: {
        color: ["#faebd7", "#03dac6", "#ff0266"],
        maxParticles: 43,
        connectParticles: false
      }
    }
  ]
});

class NavigationPage {
  constructor() {
    this.currentId = null;
    this.currentTab = null;
    this.tabContainerHeight = 70;
    this.lastScroll = 0;
    let self = this;
    $(".nav-tab").click(function () {
      self.onTabClick(event, $(this));
    });
    $(window).scroll(() => {
      this.onScroll();
    });
    $(window).resize(() => {
      this.onResize();
    });
  }

  onTabClick(event, element) {
    event.preventDefault();
    let scrollTop =
      $(element.attr("href")).offset().top - this.tabContainerHeight + 1;
    $("html, body").animate({ scrollTop: scrollTop }, 600);
  }

  onScroll() {
    this.checkHeaderPosition();
    this.findCurrentTabSelector();
    this.lastScroll = $(window).scrollTop();
  }

  onResize() {
    if (this.currentId) {
      this.setSliderCss();
    }
  }

  checkHeaderPosition() {
    const headerHeight = 75;
    if ($(window).scrollTop() > headerHeight) {
      $(".nav-container").addClass("nav-container--scrolled");
    } else {
      $(".nav-container").removeClass("nav-container--scrolled");
    }
    let offset =
      $(".nav").offset().top +
      $(".nav").height() -
      this.tabContainerHeight -
      headerHeight;
    if (
      $(window).scrollTop() > this.lastScroll &&
      $(window).scrollTop() > offset
    ) {
      $(".nav-container").addClass("nav-container--move-up");
      $(".nav-container").removeClass("nav-container--top-first");
      $(".nav-container").addClass("nav-container--top-second");
    } else if (
      $(window).scrollTop() < this.lastScroll &&
      $(window).scrollTop() > offset
    ) {
      $(".nav-container").removeClass("nav-container--move-up");
      $(".nav-container").removeClass("nav-container--top-second");
      $(".nav-container-container").addClass("nav-container--top-first");
    } else {
      $(".nav-container").removeClass("nav-container--move-up");
      $(".nav-container").removeClass("nav-container--top-first");
      $(".nav-container").removeClass("nav-container--top-second");
    }
  }

  findCurrentTabSelector(element) {
    let newCurrentId;
    let newCurrentTab;
    let self = this;
    $(".nav-tab").each(function () {
      let id = $(this).attr("href");
      let offsetTop = $(id).offset().top - self.tabContainerHeight;
      let offsetBottom =
        $(id).offset().top + $(id).height() - self.tabContainerHeight;
      if (
        $(window).scrollTop() > offsetTop &&
        $(window).scrollTop() < offsetBottom
      ) {
        newCurrentId = id;
        newCurrentTab = $(this);
      }
    });
    if (this.currentId != newCurrentId || this.currentId === null) {
      this.currentId = newCurrentId;
      this.currentTab = newCurrentTab;
      this.setSliderCss();
    }
  }

  setSliderCss() {
    let width = 0;
    let left = 0;
    if (this.currentTab) {
      width = this.currentTab.css("width");
      left = this.currentTab.offset().left;
    }
    $(".nav-tab-slider").css("width", width);
    $(".nav-tab-slider").css("left", left);
  }
}

new NavigationPage();
반응형

댓글


Copyright ⓒ SmartWeb All rights reserved.