제작기간 : 23.02.18 ~ 23.02.20 (3일)
사용 : HTML, CSS
분류 : 클론코딩, 웹 접근성, PC
- index.html
- assets/css/common.css
- assets/css/layout.css
- assets/css/main.css
- assets/css/reset.css
- assets/images/이미지파일
- assets/js/main.js
주의사항
태그별 역할
<nav class="gnb">
<ul class="nav-list" role="tablist">
<li class="nav-item"><a href="" role="tab" class="nav">서울소식</a></li>
<li class="nav-item"><a href="" role="tab" class="nav">시민참여</a></li>
<li class="nav-item"><a href="" role="tab" class="nav">분야별정보</a></li>
<li class="nav-item"><a href="" role="tab" class="nav">서울소개</a></li>
<li class="nav-item"><a href="" role="tab" class="nav">부서안내</a></li>
<li class="nav-item"><a href="" role="tab" class="nav">정보공개</a></li>
<li class="nav-item"><a href="" role="tab" class="nav">응답소</a></li>
</ul>
</nav>
<ul class="related-list">
<li class="related-item">
<a href="" role="button" class="btn-related none"><span>중앙행정기관</span></a>
</li>
</ul>
🔷window.open
자바스크립트 window 객체의 open() 함수로 웹브라우저에서 새창(팝업창)을 열 수 있음
window.open(url, name, windowFeatures);
window.open(팝업창 주소, 팝업창 이름, 팝업창 옵션);
url
새로운 창에 보여질 주소. url 설정을 안 하면 (about:blank)가 뜸.
name
새로 열릴 창의 속성 또는 창의 이름을 지정함. 기본값은 "_blank".
name(임의의 이름) - 새 창이 열리고 창의 이름을 지정함.
windowFeatures
창 크기, 리사이즈 가능 여부, 스크롤바 사용 여부 등을 설정함.
🔷location.href
location.href
현재 페이지 주소 확인
location.href = "이동할 페이지 주소"
현재 창에서 페이지 이동하기
📌html
<div class="lang-area">
<select name="#" id="langList" class="select-lang">
<option value="https://english.seoul.go.kr/?SSid=101_01">ENGLISH</option>
<option value="https://japanese.seoul.go.kr/?SSid=101_02">日本語</option>
<option value="https://chinese.seoul.go.kr/?SSid=101_04">简体中文</option>
<option value="https://tchinese.seoul.go.kr/?SSid=101_03">繁体中文</option>
<option value="https://world.seoul.go.kr/">WorldWide</option>
</select>
<button id="langBtn" class="btn-lang" aria-label="사이트로 새창 이동">GO</button>
</div>
📌js
// 둘 중에 하나 선택해서 사용할 것
$('#langBtn').click(function(){
const url=$('#langList').val();
window.open(url);
});
$('#langBtn').click(function(){
url=$('#langList').val();
location.href=url;
});
Swiper 불러오기
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/7.4.1/swiper-bundle.css">
<link rel="stylesheet" href="./assets/css/layout.css">
<link rel="stylesheet" href="./assets/css/main.css">
<link rel="icon" href="./assets/images/favicon.ico">
</head>
<body>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/7.4.1/swiper-bundle.min.js"></script>
<script src="./assets/js/main.js"></script>
</body>
Swiper 기본 구조
<div class="swiper mySwiper"> <!-- mySwiper 클래스 이름은 원하는 대로 바꿔도 됨 -->
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
...
</div>
</div>
// 순서에 의미가 있다면
<div class="swiper mySwiper">
<ul class="swiper-wrapper">
<li class="swiper-slide">Slide 1</li>
<li class="swiper-slide">Slide 2</li>
<li class="swiper-slide">Slide 3</li>
...
</ul>
</div>
📌html
<div class="btn-box">
<button class="btn prev"><span class="blind">이전</span></button>
<button class="btn autoplay"><span class="blind">자동재생 정지</span></button>
<button class="btn next"><span class="blind">다음</span></button>
</div>
📌js
const mainSlide = new Swiper('.main-slide',{
loop:true,
autoplay: {
delay: 1700,
disableOnInteraction: false // 컨트롤 후 작동 유무
},
navigation:{
nextEl:'.next',
prevEl:'.prev'
},
pagination:{
el:'.fraction',
type:'fraction'
},
});
$('.main-slide .autoplay').click(function(){
if($(this).hasClass('on')){ // 선택한 autoplay에 on 클래스가 있다면 autoplay를 시작
mainSlide.autoplay.start(); // JavaScript가 아닌 스와이퍼 자체 기능.
}else{
mainSlide.autoplay.stop(); // 없다면 autoplay를 멈춤
}
$(this).toggleClass('on'); // autoplay는 toggle. on 클래스가 있을 때 누르면 on 클래스가 빠지고 on 클래스가 없을 때 누르면 on 클래스가 들어감.
});
📌html
<div class="group-nav">
<button class="btn-nav news active" data-index="0">주요뉴스</button>
<button class="btn-nav citizen" data-index="5">시민참여</button>
</div>
📌js
const mainSlide = new Swiper('.main-slide',{
loop:true,
autoplay: {
delay: 1700,
disableOnInteraction: false
},
navigation:{
nextEl:'.next',
prevEl:'.prev'
},
pagination:{
el:'.fraction',
type:'fraction'
},
on:{ // 이벤트 핸들러. 특정 요소에서 발생하는 이벤트를 처리
"slideChange":function(){
// 현재 슬라이드가 몇 번째인지 알려줌
if(this.realIndex >= 5){ // 시민참여 슬라이드라면,
// loop에서 복제된 슬라이드를 고려한 현재 활성 슬라이드의 index
// activeIndex : 현재 활성 슬라이드의 index
$('.sc-visual .citizen').addClass('active').siblings().removeClass('active');
// .sc-visual .citizen에 active 클래스 추가하고 그 형제는 active 클래스 제거
}else{ // 주요뉴스 슬라이드라면,
$('.sc-visual .news').addClass('active').siblings().removeClass('active');
// .sc-visual .news에 ...
};
}
}
});
$('.sc-visual .group-nav .btn-nav').click(function(){
idx=$(this).data('index');
// 선택한 index값을 불러옴
$(this).addClass('active').siblings().removeClass('active');
// 클릭한 대상에게 active 클래스 추가하고 그 형제는 active 클래스 제거
mainSlide.slideToLoop(idx);
// 현재 슬라이드를 idx값을 가진 슬라이드로 이동
// 기본값은 slideTo이고 loop와 함께 사용하는 경우 slideToLoop를 써야함! (API에서 검색)
});
키보드 이벤트(Keyboard Event)는 사용자가 키를 누르거나 키를 놓을 때 발생함.
키보드 이벤트 객체에는 눌리거나 놓아진 키에 대한 다양한 메타정보가 담겨 있음.
ex) key 속성에는 키 값이, code 속성에는 코드 값이, keyCode 속성에는 키 번호 값이, shiftKey 속성에는 쉬프트키가 함께 눌렸는지 여부가 저장됨
웹 접근성을 고려하여 tab 키로 원하는 정보에 접근할 수 있게함.
- keycode === 9 : tab 키를 의미(모든 키보드는 넘버링이 있음!)
- e.shiftkey : shift 키
- ! : 부정의 의미. !로 shift를 부정함
if(e.keyCode === 9 && !e.shiftKey)
📌js
$('.sc-related .btn-related').click(function(){
if($(this).hasClass('on')){
// 또 눌렀을 때 닫겨야 함. 클릭한 대상에게 on 클래스가 있다면,
$('.sc-related .btn-related').removeClass('on').siblings('.sub-area').slideUp();
// .sc-related .btn-related의 on 클래스를 제거하고 그 형제는 슬라이드를 닫아라
return false;
// 여기에서 스크립트를 끝내라!
};
$('.sc-related .btn-related').removeClass('on').siblings('.sub-area').slideUp();
// .sc-related .btn-related의 on 클래스를 제거하고 그 형제는 슬라이드를 닫아라
$(this).addClass('on').siblings('.sub-area').slideDown();
// 클릭한 대상에게 on 클래스를 추가하고 그 형제는 슬라이드를 열어라
});
$('.sc-related .sub-list li:first-child').keydown(function(e){
keyCode = e.keyCode; // e로 이벤트 받기
if(keyCode === 9 && e.shiftKey){ // keyCode가 9번이고(tab 키), shift 키를 눌렀는지?
$('.sc-related .btn-related').removeClass('on').siblings('.sub-area').slideUp();
};
});
$('.sc-related .sub-list li:last-child').keydown(function(e){
keyCode = e.keyCode;
if(keyCode === 9 && !e.shiftKey){ // keyCode가 9번이고(tab 키), shift 키를 안 눌렀는지?
$('.sc-related .btn-related').removeClass('on').siblings('.sub-area').slideUp();
};
});
📌html
<ul class="related-list">
<li class="related-item">
<button class="btn-related"><span>직속기관·사업소</span></button>
<!-- 자식 요소가 있는 경우, button태그로 슬라이드 열고닫는 버튼 -->
<div class="sub-area">
<!-- slideUp(), slideDown()은 요소를 각각 display: none, block이 되게 함.
ul의 부모가 없을 때 요소 배치를 위해 ul에 display: flex를 준다면
slideDown()으로 ul이 block이 되어서버려서 flex가 풀림. -->
<!-- 따라서 ul을 감싸는 부모 .sub-area를 추가해서
.sub-area에 기본값으로 display: none을 주고, ul에 display: flex를 줘야함! -->
<ul class="sub-list" role="tablist">
<li><a href="" role="tab">서울시립대학교</a></li>
...
</ul>
</div>
</li>
<li class="related-item">
<a href="" role="button" class="btn-related none"><span>중앙행정기관</span></a>
<!-- 자식 요소가 없는 경우, a태그로 바로 링크 이동 -->
</li>
</ul>
📌css
.sc-related .related-item .btn-related:not(.none) span{
/* 글씨 길이와 상관없이 일정한 간격으로 떨어진 화살표를 넣기 위해서 기준이 되는 span을 추가함 */
position: relative;
padding-right: 20px;
}
.sc-related .related-item .btn-related:not(.none) span::after{
/* 화살표를 만들어서 위치시킴 */
position: absolute;
top: 8px;
right: 0px;
height: 7px;
width: 7px;
border-style: solid;
border-color: #373737;
border-width: 0px 2px 2px 0px;
transform: rotate(-135deg);
/* 화살표 회전 전 각도 */
transition: all .3s;
transform-origin: center center;
content: '';
}
.sc-related .related-item .btn-related.on:not(.none){
background: #e2e2e2;
}
.sc-related .related-item .btn-related.on:not(.none) span::after{
top: 4px;
transform: rotate(45deg);
/* 화살표 회전 후 각도*/
transform-origin: center center;
}
.sc-related .sub-area{
/* slideDown()이 적용되면 display: block으로 바뀜. slideUp()은 다시 none으로 돌아옴 */
display: none;
position: absolute;
bottom: calc(100% - 1px);
left: 0;
width: 100%;
padding: 10px 20px 20px;
background: #fff;
border: 1px solid #d0d0d0;
}
.sc-related .sub-area .sub-list{
/* 자식 요소를 flex로 배치 */
display: flex;
flex-wrap: wrap;
}
📌html
<div class="fix-btn">
<button class="btn-top"><span class="blind">상단으로</span></button>
</div>
📌css
.fix-btn{
/* 버튼을 중심을 기준으로 위치시켰기 때문에, 화면 크기를 조절해도 항상 위치가 똑같음 */
position: fixed;
bottom: 98px;
left: 50%;
margin-left: 600px;
}
.fix-btn .btn-top{
/* display: none과 block간의 변화는 transition 효과를 줄 수 없으므로,
transition 효과가 필요하면 opacity: 0과 visibility: hidden으로 숨긴 뒤
opacity: 1과 visibility: visible로 보이게 해야함! */
display: block;
width: 34px;
height: 34px;
opacity: 0;
visibility: hidden;
transition: 1s;
transform: translateY(300px);
/* 버튼을 밑에 숨겨놓을 때 위치 */
}
.fix-btn .btn-top.show{
opacity: 1;
visibility: visible;
transform: translateY(0);
/* 버튼이 보일 때 위치 */
}
📌js
$(window).scroll(function(){
curr=$(this).scrollTop(); // 현재 스크롤바의 수직 위치 값
if(curr >= 20){
$('.fix-btn .btn-top').addClass('show'); // curr가 20 이상이면 show 클래스 추가
}else{
$('.fix-btn .btn-top').removeClass('show'); // 20 미만이면 show 클래스 제거
};
});
$('.fix-btn .btn-top').click(function(){
window.scrollTo({top:0,behavior:"smooth"}); // 스크롤바가 부드럽게 최상단으로 이동
});
The W3C Markup Validation Service의 Nu Html Checker를 통해 index.html의 마크업이 웹 표준에 적합함을 확인했습니다.