Skip to content

Latest commit

 

History

History
206 lines (193 loc) · 17.3 KB

20210224.md

File metadata and controls

206 lines (193 loc) · 17.3 KB

HTML5 and CSS3

지난 시간 로고를 위치시키고 안내링크 모음까지 했으니 header의 나머지 영역인 메인 메뉴와 그 밑의 하위 메뉴를 작업해본다.

메인 메뉴

<nav> Mark-up

  • 지난 시간 작업한 상황에서 로고는 position이 absolute가 되면서 떠올랐기 때문에 별도의 height 값이 없어진 상위요소 header은 높이가 안내링크 영역만큼으로 줄어들었다.
    • 이를 해결하기 위해 nav를 만듦으로써 header를 적절한 크기로 늘리자.
  • 시안의 메뉴 바 (HTML에 대해, CSS에 대해, ..., 자료실) 부분을 클릭하면, 링크로 이동하는 것이 아니라 하위 항목만 보이게끔 만들어주자. (현재 hover만 해도 하위 항목이 보이는 시안과는 다르게 해보기)
  • 하위 항목을 지정해주기 위해 <nav class="navigation"> 안에 <ul class="menu">을 두어 묶어주고, 각 메뉴는 <li class="menu-item"> 속 링크 <a class="menu-item-button"> 태그로 한다.
    • ul의 자식요소는 li만 올수가 있기 때문에 반드시 li 안에 다른 태그가 오는 순서로!
    • 메인 바의 메뉴에 어떤 태그를 쓸지 고민해보자.
      • span을 쓰면 클릭 이벤트를 발생시킬 수가 없다.
      • button을 쓰면 클릭은 가능하지만 border-box를 비롯하여 default로 주어지는 다양한 속성을 재정의해야 하며 같은 맥락에서 cross-browser 시의 customizing이 까다롭다.
      • 그렇다면 a 태그로 하되 button의 역할을 하도록 ARIA를 사용하는 방법이 있다. a태그에 role="button"을 넣어주고, href="#" class="menu-item-button"으로 지정
    • 하위 항목들은 별도의 스타일로 꾸며줘야 하므로 li 속 <ul class="sub-menu"로 묶어준다.

다양한 css파일 import하는 방법

  • import는 무조건 첫 줄에 써야 컴퓨터 읽기 순서(위->아래)상 문제가 없다.
  • normalize.css 가져오기
    • style.css의 첫 줄에 @import url(./normalize.css);
    • index.html에 style.css 링크하듯 <link rel="normalize" href="css/normalize.css"> : 이 방법은 파일 여러개일 때 관리가 귀찮아지니까, 개발용에는 css source 파일 여러개를 따로 import하여 관리하되, 배포(distribution file)용에는 하나의 파일을 만들어 html에 하나만 링크한다. (source files를 모두 합치고 줄바꿈도 없게 uglify한 하나의 css파일 main.css로)
    • Sass라는 CSS 전처리기는 위와 같이 각 모듈별로 쪼개놓고 하나로 만들어주는 것까지 다 해주는 기능을 가진다.
  • 웹폰트 가져오기
    • 폰트를 웹에서 가져오면 브라우저마다 해당 글꼴이 달라질 염려가 없다.
    • 구글과 어도비의 합작인 Spoqa Han Sans를 데려오자.
    • 구글링한 깃헙 소스코드 @import url(//spoqa.github.io/spoqa-han-sans/css/SpoqaHanSansNeo.css);
    • 잘 import되었나 확인하려면 적용된 페이지에 가서 개발자도구-Network-Font

숨김 콘텐츠 처리

  • markup 상에는 존재하되 화면에는 나오지 않아야하는 부분이 있다. 일반인은 맥락을 통해 유추할 수 있고 디자인 상 보이지 않지만 시각장애인을 위한 스크린리더에는 읽혀야하는 부분 등이다.
  • 이런 부분들에 class명을 a11y-hidden 등으로 준 후 숨김콘텐츠로 처리하여 접근성을 확보할 수 있다.
  • (Wrong) .a11y-hidden{display: none;}: 기껏 숨김콘텐츠 만들어놓고 접근성을 아예 없애버리는 짓
  • (Old way) .a11y-hidden{position: absolute; top:-9999px;}: 일명 안드로메다로 보내버리기 전략이지만 이렇게 할 경우 이 부분을 screen reader가 위치를 잡기 위해 top좌표를 찾아가면서 갑자기 스크롤바가 생기는 일이 발생
  • (New better way) 스크롤바가 튀지 않도록 제자리에 있으면서도 보이지는 않게 하는 방법이 있다.
    • .a11y-hidden{width: 1px; height: 1px; margin: -1px; overflow: hidden;}으로 하면 제자리에 존재하긴 하면서 보이지 않는다.
    • 이렇게 할 때 몇몇 경우엔 점이 생기는데 그 점까지 없애주려면 clip-path 속성을 이용한다. clip-path: polygon(0 0, 0 0, 0 0);을 주면 영역이 전혀 보이지 않는다.
      • clip-path는 IE 하위버전에서는 안 되기 때문에 IE하위버전에서는 clip: rect(0 0 0 0)로 해줘야 하지만 잘 안 쓰이는 속성이라 권장은 X

<nav> Design Coding

  1. menu로 네이밍한 <nav> 속 ul에 메뉴바 스타일 입히기.
  • ul 스타일 초기화: agent(browser)의 default값으로 주어진 margin, padding, list-style을 0과 none으로 제거해준다.
    • 앞으로 나올 ul, ol 스타일도 동일하게 작업해주려면 아예 mark-up 상 태그에 class이름에 reset-list를 추가해서 초기화해준다.
/* 스타일 초기화 */
.reset-list{
	list-style-type: none;
	padding-left: 0;
	margin: 0;
}

element(ul)에 스타일을 주기보다는 이처럼 class(.reset-list)에 스타일을 주어야 추후에 있을 변경에 대해서 유연하게 대응할 수 있다.

  • 배경색 입히기: background: linear-gradient(to bottom, 시작색깔 0%, 중간색깔 00%, ..., 끝색깔 100%);
    • CSS3 gradient generator 가서 그라데이션 설정 후 코드값을 복사
    • 개발단계에서는 표준코드만 복붙하더라도 나중에 cross-browser을 어디까지 할 건지에 따라서 prefix가 달라진다는 점을 유념하여 필요한 코드를 복붙
    • 위와 같은 고민을 하지 않아도 되게끔 Post CSS가 prefix를 알아서 붙여주기도 한다.
    • 우리는 그냥 표준코드만 넣어주되 호환 안되는 브라우저를 위해 해당 배경그라디언트가 뜨지 않을 경우 나올 background 색깔을 fall-back으로 넣어줄 것(콤마 없이 앞에 넣어주면 된다)
  • 메뉴바 위에 검은색 선 입히기
    • border-top: 2px solid #000; 상자 크기에 영향 주니까 고려하며 사이즈 조정 필요
    • box-shadow: 0 -2px 0 0 #000;로 주는 방법도 있지만 우리는 위의 방법으로 하고 상자 크기를 2px 더해주자.
  • header 기준으로 위는 안내링크모음 다음으로 위치하고 좌우와 아래는 떨어지게끔 header{padding: 0 30px 35px;}
  • 둥근모서리가 아래쪽에만 들어가므로 border-radius: 0 0 5px 5px;
    • border-radius의 값은 공백으로 구분하며 순서는 left-top부터 시계방향
    • /를 통해 x축과 y축의 값 지정도 가능 (e.g. border-radius: 0 0 30px 30px / 0 0 5px 5px)
  1. 메뉴 바 및 활성화된 메뉴 항목 꾸미기
  • 상위 메뉴는 float로, 하위 메뉴는 inline-block으로 쌓아주자
  • 상위 메뉴인 menu-item을 float:left
    • menu-item들이 하위메뉴의 너비만큼 서로 떨어져 있어서 원하는 결과(서로서로 옆에 붙은 모양)가 나오지 않는다. 이럴 때 하위 메뉴인 ul submenu에 position:absolute를 줌으로써 하위메뉴의 width가 아예 인식되지 않게 한다.
    • 부모요소인 menu는 높이를 잃어버리므로 overflow를 쓰거나 가상요소 ::after로 clear를 해줘야 한다. 하지만 overflow:hidden을 할 경우 하위메뉴도 숨겨진다는 단점도 있고 하니 이번에는 더이상 추가될 메뉴가 없다고 가정하고 menu에 직접 높이를 준다.
    • 아까 border-top 줬던 것을 감안하여 45px height를 주려면 47px로 줘야 한다.
  • menu-item이 로고부분 이후 위치하게 하기 위해 menu에 padding-left를 주거나 menu-item에 margin-left를 준다.
    • 그러나 후자의 경우 줄바꿈시 로고영역을 침범하니까 안전한 전자를 선택
  • 왼쪽에 하얀 경계선을 넣어주기 위해 border-left: 1px solid #fff;
  • menu-item들의 안쪽 여백을 주되, 링크영역이 넓어여 클릭하기 쉬우니까 menu-item의 a태그 클래스인 menu-item-button를 block으로 만든 후 padding 주되 아까 menu에 border-top들어가있으니 top에 2px 주고 좌우는 20px로 padding: 2px 20px 0;
  • 위와 동일한 선택자에 글자 테두리 효과 text-shadow: 1px 1px 0 #000, -1px -1px 0 #000;
  • line-height를 이젠 45px로 하여 메뉴 높이와 같도록.
  • 이제 하위 항목 중 클릭된 항목인 menu-act로 지정된 부분을 꾸며준다.
    • 그냥 menu-act만 선택하면 그 하위 요소는 자기의 값을 그대로 가져간다. 더 구체적으로 menu-act 속 menu-item-button까지 선택해주자.
    • color: yellow;로 글자색을 바꿔준다
    • 밑줄을 넣기 위해 border-bottom을 하면 padding 부분인 전체 메뉴에 밑줄이 들어가지만 우리가 원하는 건 글자부분에만 밑줄이 들어가는 것이므로 .menu-item-button::after을 만들어준 후 content:""로 존재하게 하고, 옆에 붙어 정렬되지 않도록 display:block을 해준 후 background-color: #000을 주고 height를 2px로 준 후 margin-top: -2px로 끌어올려 menu-item-button의 높이 47px에다가 padding-top으로 2px 오버된 아래부분에 겹쳐지게 한다. border-bottom으로 줄 수도 있지만 이렇게 하면 shadow를 줄 수도 있고 하니...(이부분이 약간 tricky...)
  1. 하위메뉴(sub-menu) 스타일링
  • 상위메뉴의 line-height가 상속되지 않게 하려면 menu-item이 아닌 menu-item-button에 주는 것이 좋다. 안 그러면 하위 메뉴도 간격이 위아래로 널찍.
  • 아까 상위메뉴의 너비에 영향을 주지 않기 위해 하위메뉴의 position을 absolute로 주었고, offset parent 요소는 header인 상태
    • header에게 다른 작업을 할 경우 영향을 받을 수도 있으니, 이왕이면 더 가까운 부모요소에게 주는 것이 안전
    • 각 하위메뉴의 상위메뉴인 li(menu-item)를 offset parent로 설정해주기 위해 .menu-item{position: relative;}를 넣어준다.
    • 메뉴바에서 밑으로 47px 떨어져있어야 하므로 top: 47px
    • 첫 3개의 sub-menu는 상위메뉴의 좌측을 기준으로, 나머지 3개는 상위메뉴의 우측을 기준으로 배치한다. .sub-menu1, .sub-menu2, .sub-menu3 {left:0;} .sub-menu4, .sub-menu5, .sub-menu6 {right:0;}
  • 하위메뉴를 가로로 흘러가게끔 하기 위해 .sub-menu li {display: inline-block;}
    • 그러나 이 경우 sub-menu가 부모요소 크기만큼만 좌우로 흘러가므로 밑으로 내려간다. 이를 방지하기 위해 따로 sub-menu에 width를 줘도 되지만 white-space: nowrap로 간단하게 줄바꿈 금지를 선언할 수 있다.
  • 하위메뉴의 bullet point를 따로 만들어 넣어주기 위해서는 font awesome이나 fontello 등의 서비스를 이용할 수 있다.
    • 우리는 준비된 fontello.css를 import하고 하위메뉴의 a 태그에 해당 클래스 이름을 넣으면 알아서 ::before 요소를 만들어 아이콘이 자리잡는다.
  • a태그에도 위아래로 여백을 넣어 링크 클릭을 조금 더 용이하게끔 넓혀주기 위해 inline-block화 시킨다. 좌우 패딩은 0으로 하고 margin-right도 넣어서 각 링크마다 구분되게끔, 그리고 마우스를 갖다대거나 포커스를 받았을 때 글자 색이 빨갛게 되도록 처리한다.
.sub-menu a{
  display: inline-block;
  padding: 10px 0 8px;
  margin-right: 5px;
}
.sub-menu a:hover, .sub-menu a:focus{
  color: #f00;
}

비주얼 영역 <div class="visual"> 애니메이션

  • 비주얼 영역의 높이는 앞으로도 변하지 않는다는 전제 하에 120px로.
  • 배경그림 위의 글자는 mark-up에 추가하여 애니메이션을 줘보자.
    • div로 넣고 클래스를 visual-text로.
    • 글자 내용 중 &와 같은 기호는 경우에 따라 반드시 변환해야하는 특수문자일 때도 있으니 안전하게 &amp;로 입력해준다. 그 외의 특수문자들은 html entities로 찾아보면 나오며 업데이트는 잘 안되지만 W3C schools에서도 확인 가능, 특히 화폐기호는 복붙하지말고 이런 entity 값으로 넣어주는 게 좋다.
  • 배경그림은 background에서 넣어 처리해보자. CSS의 multi-background 기능을 활용해볼 것.

애니메이션 시나리오 짜기 - 텍스트 부분

  1. 이름지정: 텍스트 파트니까 textAni로.
  2. 액션 정의: 글자의 이동, 투명도 변화, 글자크기 변화를 볼 수 있다.
  • 글자는 좌상단(0, 0)에서 우하단(top 75px, left 400px)로 이동
    • position: absolute;: offset parent를 선택해주어야 하므로 visual의 position을 relative로 주는 작업 필수.
    • 글자의 margin값이나 div의 padding 값을 점점 늘려주는 방식: 글자에 margin을 주면 텍스트를 포함한 visual 영역 자체가 margin값을 가지므로 padding으로 줘야 함
    • transform: translate (x좌표, y좌표);: 좌우로 긴 블록 크기 그대로 이동하기 때문에 이동 후 스크롤바가 생긴다. 이를 방지하기 위해 visual text를 inline-block으로 처리해주거나 width 값을 임의로 지정해줘야.
    • 위 세가지 모두 같은 효과를 주지만 reflow를 발생시키며 성능 문제를 일으킨다. 특히 position을 바꾸는 것은 움직일 때마다 매번 다시 그리기 때문에 GPU를 완전 많이 차지한다. 가장 성능면에서 효율적인 transform을 사용하도록 하자.
  • font-size를 점점 키워준다
  • 투명도에 변화를 준다.
    • opacity로 주면 상자 전체의 투명도가 조절된다.
    • 텍스트 투명도만 조절하려면 color: rgba(0 0 0 0)로 alpha값을 준다.
  1. CSS에 애니메이션 정의
@keyframes textAni{
  0% { #처음 시작할 때의 값을 다 넣어준다. 0% 대신 from으로 넣어도 되지만 form과 헷갈리니까 0%으로.
    font-size: 12px;
    color: rgba(0, 0, 0, 0);
    transform: translate (0, 0);
  }
  100% {
    font-size: 24px;
    color: rgba(0, 0, 0, 1);
    transform: translate (400px, 75px);
  }
}

이제 이렇게 정의해준 애니메이션을 받을 선택자를 연결해주되, 두가지를 꼭 넣어주어야 애니메이션이 동작한다.

  • .visual-text {animation-name: textAni; animation-duration: 2000ms;}
  • 이렇게만 하면 애니메이션이 100%에 도달한 이후 다시 0%의 값으로 끝나는데, 100%로 지정한 상태로 머물게 하려면 animation-fill-mode: forwards;를 넣어주어야 한다.
  • 글씨체도 바꿔준다.
.visual-text {
  animation-name: textAni;
  animation-duration: 2000ms;
  animation-fill-mode: forwards;
  font-family: Georgia, font1, font2 #Geargia가 지원되지 않는 경우 등장할 다른 폰트들
}

애니메이션 시나리오 짜기 - 꽃과 나무 부분

  1. 이름지정: background에 이미지를 넣어 애니메이션을 줄 거니까 bgAni로.
  2. 액션 정의: 꽃들이 번갈아가며 등장 및 사라진다. 시간차를 두어 투명도 주기.
  3. CSS에서 작업해주기.
  • 두개의 꽃세트를 만들기 위해 두 가상요소선택자를 부모영역 크기만큼 겹쳐만들고 그 안에 background image를 absolute로 position으로 주도록 하자.
  • markup으로 새로운 빈 div를 주는 방법도 있지만 multi-background를 활용해보자
  • before에 꽃 두개, after에 꽃 두개를 각각 콤마로 넣어준다. multi-background에서는 콤마로 하면 영원히 추가 가능
    • .visual::before {background: url(이미지1주소) no-repeat x축값 y축값, url(이미지2주소) no-repeat x축값 y축값;}
    • 위 방법과 결과는 같지만 no-repeat 등 중복되는 부분의 효율화를 위해 visual에 background: no-repeat; 넣어주고 .visual::before {background-image: url(이미지1 주소), url(이미지2주소); background-position: 이미지1 좌표값, 이미지2 좌표값;}로 넣어준다.
  • 애니메이션은 투명도만 조절해주면 되는 문제이므로 opacity: 0 (0%) 또는 1 (100%);로.
  • 꽃이 사라졌다가 다시 나타나는 애니메이션의 반복
    • 계속해서 애니메이션이 동작하도록 animation-iteration-count: infinite;
    • @keyframes bgAni에 0%, 50%, 100%로 줄 수도 있지만 animation-direction: alternate;으로 하면 알아서 방향이 앞뒤로 오간다.
@keyframes bgAni{
  0% {
    opacity: 0;
  }
  100% {
    opacity: 100%;
  }
}
.visual::before, .visual::after{
  content: "";
  position: absolute; #부모 영역인 .visual에도 position:relative 해서 offset parent로 만들어줄 것
  top: 0;
  left: 0;
  width: 100%;
  height: 100%; #부모영역과 동일
  background: no-repeat;
  animation-name: bgAni;
  animation-duration: 2000ms;
  animation-iteratio-count: infinite;
  animation-direction: alternate;
}
  • 꽃이 시간차를 두고 등장해야하기 때문에 .visual::after의 animation은 딜레이값을 준다.
.visual::before{
  background-image: url(이미지1주소), url(이미지2주소);
  background-position: 이미지1 좌표, 이미지2 좌표;
}
.visual::after{
  background-image: url(이미지3주소), url(이미지4주소);
  background-position: 이미지3 좌표, 이미지4 좌표;
  animation-delay: 1000ms;
}

느낀 점

  • 숨김콘텐츠나 reset-list처럼 간단하게 처리하는 방법들을 고안해낸 사람은 누굴까. 정말 대단하다...
  • CSS에서 효과적으로 애니메이션을 표현할 수 있다니 신기하다.