프론트엔드/HTML & CSS 연습과제 해답

스크롤바 연습과제

syleemomo 2023. 7. 20. 17:57
728x90

완성화면

스크롤을 조금 내리면 헤더가 나타나고 scroll to top 버튼도 함께 나타난다.

모달창 오픈

open 버튼을 클릭하면 모달창이 나타나고 뒷배경은 음영처리된다. 또한, 모달창을 확인하는동안 뒷배경이 스크롤되지 않도록 스크롤바는 숨긴다. close 버튼을 클릭하면 모달창이 사라지고 다시 스크롤바가 나타난다.

 

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link href="https://cdn.jsdelivr.net/npm/remixicon@2.2.0/fonts/remixicon.css" rel="stylesheet">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <nav>
    <ul>
      <li><a href="#">story</a></li>
      <li><a href="#">about</a></li>
      <li><a href="#">contact</a></li>
    </ul>
  </nav>
  <button type="button" class="open">OPEN</button>
  <a href="#" class="arrow-up"><i class="ri-arrow-up-circle-fill"></i></a>
  <div class="container">
    <div class="modal-window">
      <div class="modal-header line">header</div>
      <div class="modal-body line">
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis officia, tempora ipsam libero expedita, doloribus velit eveniet delectus omnis nostrum consectetur magnam tempore quas explicabo mollitia laboriosam eos aut ex?
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis officia, tempora ipsam libero expedita, doloribus velit eveniet delectus omnis nostrum consectetur magnam tempore quas explicabo mollitia laboriosam eos aut ex?
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis officia, tempora ipsam libero expedita, doloribus velit eveniet delectus omnis nostrum consectetur magnam tempore quas explicabo mollitia laboriosam eos aut ex?
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis officia, tempora ipsam libero expedita, doloribus velit eveniet delectus omnis nostrum consectetur magnam tempore quas explicabo mollitia laboriosam eos aut ex?
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis officia, tempora ipsam libero expedita, doloribus velit eveniet delectus omnis nostrum consectetur magnam tempore quas explicabo mollitia laboriosam eos aut ex?
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis officia, tempora ipsam libero expedita, doloribus velit eveniet delectus omnis nostrum consectetur magnam tempore quas explicabo mollitia laboriosam eos aut ex?
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis officia, tempora ipsam libero expedita, doloribus velit eveniet delectus omnis nostrum consectetur magnam tempore quas explicabo mollitia laboriosam eos aut ex?
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Corporis officia, tempora ipsam libero expedita, doloribus velit eveniet delectus omnis nostrum consectetur magnam tempore quas explicabo mollitia laboriosam eos aut ex?
      </div>
      <button type="button" class="close">CLOSE</button>
    </div>
  </div>
  <script src="app.js"></script>
</body>
</html>
*{
  box-sizing: border-box;
}
::-moz-selection {
  background-color: orange;
}
::selection{
  background-color: orange;
}
body{
  margin: 0; padding: 0;
  background-image: url('https://t1.daumcdn.net/cfile/tistory/1558F93C4E5DA85E36');
  background-position: center center;
  background-size: contain;
  width: 100%;
  max-width: 100%; 
  min-height: 300vh;
  position: sticky; top: 0; /* position: static 이면 z-index 동작하지 않음 */
  z-index: -3; /* z-index 값이 없으면 닫기 버튼이 눌리지 않음 */
}
nav{
  position: fixed;
  width: 100%;
  top: 0; left: 0;
  height: 50px;
  z-index: -2;
  color: #fff;
  background: rgba(0, 0, 0, .3);
  display: none;
}
nav ul{
  padding: 0; margin: 0;
  list-style: none;
  display: flex;
  justify-content: flex-end;
}
nav > ul > li > a{
  text-decoration: none;
  color: #fff;
  margin-right: .5rem;
  transition: .3s;
}
nav > ul > li > a:hover{
  letter-spacing: 1px;
}
.container{
  position: fixed;
  left: 0; top: 0;
  max-width: 100%;
  width: 100%; max-height: 100vh; height: 100vh;
  background-color: rgba(0, 0, 0, .7);
  z-index: -1;
  display: none;
  justify-content: center;
}
.modal-window{
  position: relative;
  justify-content: flex-start;
  background-color: rgba(0, 0, 0, .3);
  max-width: 450px; width: 80%;
  height: 300px;
  border-radius: .5rem;
  backdrop-filter: blur(3px);
  text-align: left;
  color: #fff;
  display: none;
  padding: 20px;
  transition: .3s;
  box-shadow: 0 0 1rem rgba(255, 255, 255, .1);
  z-index: 2;
  overflow: auto;
  -ms-overflow-style: none; /* IE and Edge */
  scrollbar-width: none; /* Firefox */
}

.modal-window::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Opera*/
}
.show{
  display: flex;
  flex-flow: column;
  align-items: center;
}
.hide{
  display: none;
}
.show-nav{
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
button{
  border: none; outline: none;
  border-radius: .5rem;
  width: 5rem;
  background: rgba(0, 0, 0, .3);
  padding: .5rem;
  cursor: pointer;
  font-weight: bold;
  color: #fff;
  /* box-shadow: 0 0 .3rem rgba(255, 255, 255, .3); */
  transition: .3s;
}
button:hover{
  background-color: rgba(0, 0, 0, .5);
}
.open{
  position: fixed;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
}
.close{
  position: sticky;
  /* right: 10px; */
  bottom: 0px;
  height: 30px;
}
.modal-header,
.modal-body,
.modal-footer{
  width: 100%;
}
.modal-header,
.modal-footer{
  height: 50px;
}
.modal-header,
.modal-body{
  /* padding: 1rem; */
}
.modal-header{
  /* background-color: red; */
}
.modal-body{
  flex: 1;
  /* background-color: green; */
}
.modal-footer{
  /* background-color: blue; */
}
.line{
  border-bottom: 1px solid rgba(255, 255, 255, .3);
}

.arrow-up{
  position: fixed;
  right: 2rem;
  bottom: 2rem;
  background: rgba(0, 0, 0, .3);
  border-radius: 50%;
  color: #fff;
  width: 50px; height: 50px;
  line-height: 50px;
  text-align: center;
  z-index: -2;
  display: none;
}
.arrow-up:hover{
  background-color: rgba(0, 0, 0, .5);
}
.show-arrow-up{
  display: block;
}
const openBtn = document.querySelector('.open')
const closeBtn = document.querySelector('.close')
const modalWindow = document.querySelector('.modal-window')
const container = document.querySelector('.container')
const scrollToTopBtn = document.querySelector('.arrow-up')
const nav = document.querySelector('nav')
const navHeight = 50
let clientWidth = document.documentElement.clientWidth

function openModal(){
  const padding = document.documentElement.clientWidth - clientWidth
  modalWindow.classList.add('show')
  container.classList.add('show')
  document.body.style.overflow = "hidden"
  openBtn.classList.add('hide')
  // document.body.style.paddingRight = `16px`
  // container.style.paddingRight = `16px`
}
function closeModal(){
  const padding = document.documentElement.clientWidth - clientWidth
  modalWindow.classList.remove('show')
  container.classList.remove('show')
  document.body.style.overflow = ""
  openBtn.classList.remove('hide')
}
function checkScrollPosition(){
  console.log(window.pageYOffset)
  if(window.pageYOffset > 100){
    scrollToTopBtn.classList.add('show-arrow-up')
  }else{
    scrollToTopBtn.classList.remove('show-arrow-up')
  }
  if(window.pageYOffset > navHeight){
    nav.classList.add('show-nav')
  }else{
    nav.classList.remove('show-nav')
  }
}
function scrollToTop(e){
  e.preventDefault()
  window.scrollTo({ top: 0, behavior: 'smooth'})
}
openBtn.addEventListener('click', openModal)
closeBtn.addEventListener('click', closeModal)
scrollToTopBtn.addEventListener('click', scrollToTop)
window.addEventListener('scroll', checkScrollPosition)
728x90