본문 바로가기
Project/더퓨어웹사이트 프로젝트

[pureapp 프로젝트] 반응형 시멘틱 마크업 공부

by 히앤님 2023. 3. 28.
반응형
SMALL

🔶 시멘틱 마크업

div, section, article, h2 등 수많은 태그들을 문서 내용에 맞게 선택해서 사용하는 것

 

[ 장점 ]

1. SEO - 검색엔진 최적화에 유리

2. 웹접근성 - 시각장애인들도 웹을 편리하게 접할 수있도록 도와줌

3. 유지보수 - 정리된 마크업은 코드 식별이 용이함

 

출처 : 드림코딩 엘리

위와 같은 형식으로 div 떡칠하지 말고 의미있는 마크업으로 만들어보자.

 

📢 목표 : 반응형 시멘틱 마크업 분석해서 적용하기

- 모바일에서는 nav가 토글로 숨겨질 것(js사용)

- main 안에 열을 두개로 설정하여 aside를 넣을 것

- 모바일에서 일정 너비로 줄어들면 aside는 아래로 내려갈 것

- scss 문법을 사용할 것

 

📢 vsCode 에서 Sass 사용하기

Live Sass Compiler

node로 sass를 설치해서 package.json에 수작업으로 자동 컴파일을 하는 환경을 세팅할 수도 있지만, vscode에서 제공되는 Live Sass Compiler라는 플러그인을 사용하면 알아서 해준다.

 

sass 파일 수정 -> css 파일 만듦(map은 매핑을 위한 파일) -> 만들어진 css를 import 해서 사용함.

 

 

❗ 반응형으로 헤더 네비게이션 및 2개의 열 설정한 템플릿 분석

pc버전
모바일 버전

🟡 HTML 코드

🔽 전체보기

더보기

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My Blog</title>
        <link rel="stylesheet" href="samplePage4.css">

    </head>
    <body>
        <header>
            <div class="container">
                <h1>My Blog</h1>
                <nav>
                    <ul class="nav-menu">
                        <li>
                            <a href="#">Home</a>
                        </li>
                        <li>
                            <a href="#">Blog</a>
                        </li>
                        <li>
                            <a href="#">About</a>
                        </li>
                        <li>
                            <a href="#">Contact</a>
                        </li>
                    </ul>
                    <div class="mobile-menu">
                        <span></span>
                        <span></span>
                        <span></span>
                    </div>
                </nav>
            </div>
        </header>
        <main>
            <section>
                <article>
                    <h2>Article Title 1</h2>
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel nulla eget
                        lectus tempor rhoncus.</p>
                    <a href="#">Read More</a>
                </article>
                <article>
                    <h2>Article Title 2</h2>
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel nulla eget
                        lectus tempor rhoncus.</p>
                    <a href="#">Read More</a>
                </article>
                <article>
                    <h2>Article Title 3</h2>
                    <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel nulla eget
                        lectus tempor rhoncus.</p>
                    <a href="#">Read More</a>
                </article>
            </section>
            <aside>
                <h2>About Me</h2>
                <p>Hi there! My name is John and I'm a blogger. Lorem ipsum dolor sit amet,
                    consectetur adipiscing elit. Sed vel nulla eget lectus tempor rhoncus. Proin
                    gravida dictum lorem, non porttitor arcu bibendum non. Integer non magna sit
                    amet nulla tincidunt tincidunt eu vel ipsum. Duis interdum vulputate ante, vel
                    tempus massa blandit ut. Aenean viverra orci quis justo lobortis, ac mattis
                    augue tincidunt.</p>
                <p>If you have any questions or comments, feel free to contact me at
                    john@myblog.com</p>
            </aside>
        </main>
        <footer>
            <p>&copy; 2023 My Blog</p>
        </footer>
        <script>
            /* Toggle mobile navigation menu */
            const menuIcon = document.querySelector('.mobile-menu');
            const navMenu = document.querySelector('.nav-menu');

            menuIcon.addEventListener('click', () => {
                navMenu.classList.toggle('show');
            });
        </script>
    </body>
</html>

 

🟨 구조 분석

참고 링크 : https://developer.mozilla.org/ko/docs/Web/HTML/Element

<!DOCTYPE html>
<html lang="ko">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My Blog</title>
        <link rel="stylesheet" href="samplePage4.css">
    </head>

<!DOCTYPE html>

선언된 페이지의 HTML 버전이 무엇인지 웹 브라우저에 알려줌.

 

<meta charset="UTF-8">

선언된 페이지의 정보(메타데이터) 중 문자 인코딩 방식 명시

 

<meta name="viewport" content="width=device-width, initial-scale=1.0">

선언된 페이지의 정보(메타데이터) 중 뷰포트(viewport) 설정.

width=device-width 는 너비를 장치 너비로 설정한다는 말

initial-scale=1.0 초기 화면 배율을 1.0(100%)로 설정한다는 말

 

header

<body>
    <header>
        <div class="container">
            <h1>My Blog</h1>
            <nav>
                <ul class="nav-menu">
                    <li>
                        <a href="#">Home</a>
                    </li>
                    <li>
                        <a href="#">Blog</a>
                    </li>
                    <li>
                        <a href="#">About</a>
                    </li>
                    <li>
                        <a href="#">Contact</a>
                    </li>
                </ul>
                <div class="mobile-menu">
                    <span></span>
                    <span></span>
                    <span></span>
                </div>
            </nav>
        </div>
    </header>

<header> <div class="container">

header 부분을 div로 한번 더 감싸서 css 적용함. 헤더 전체의 컬러와 padding 이외에 배치는 container class에 설정한다.

 

<ul> <ol> <li>

<ul> : 순서가 필요 없는 목록(li 사용 시 점이 생김)

<ol> : 순서가 있는 목록(li 사용 시 순번이 생김)

<li> : 각 항목을 나열할 때(list item)

 

<dl> <dt> <dd>

<dl> : 사전처럼 용어를 설명하는 목록

<dt> : 용어의 제목을 설정

<dd> : 용어의 설명을 설정(자동 들여쓰기 적용)

 

<span>

보통은 인라인 컨테이너로 어떤 특성의 값을 묶을 때 사용.

저렇게 선언한 후 색상, width, height, margin을 주면 햄버거 모양이 만들어진다.

 

main

<main>
    <section>
        <article>
            <h2>Article Title 1</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel nulla eget
                lectus tempor rhoncus.</p>
            <a href="#">Read More</a>
        </article>
        <article>
            <h2>Article Title 2</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel nulla eget
                lectus tempor rhoncus.</p>
            <a href="#">Read More</a>
        </article>
        <article>
            <h2>Article Title 3</h2>
            <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vel nulla eget
                lectus tempor rhoncus.</p>
            <a href="#">Read More</a>
        </article>
    </section>
    <aside>
        <h2>About Me</h2>
        <p>Hi there! My name is John and I'm a blogger. Lorem ipsum dolor sit amet,
            consectetur adipiscing elit. Sed vel nulla eget lectus tempor rhoncus. Proin
            gravida dictum lorem, non porttitor arcu bibendum non. Integer non magna sit
            amet nulla tincidunt tincidunt eu vel ipsum. Duis interdum vulputate ante, vel
            tempus massa blandit ut. Aenean viverra orci quis justo lobortis, ac mattis
            augue tincidunt.</p>
        <p>If you have any questions or comments, feel free to contact me at
            john@myblog.com</p>
    </aside>
</main>

<main> <section> <article> <aside>

<main> : body의 주요 콘텐츠

<section> : 독립적인 구획을 나타냄. 이 경우, aside 영역 말고 메인영역으로 나눔

<article> : 독립적인 구획을 여러개 나열할 때 사용. (ex. 게시글 목록)

<aside> : 주요 내용과 간접적으로 연관됨. 사이드 구획으로 많이 사용함.

 

<p>

하나의 문단을 의미함. 글을 쓸 때 Enter 같은 것.

 

footer

    <footer>
        <p>&copy; 2023 My Blog</p>
    </footer>
    <script>
        /* Toggle mobile navigation menu */
        const menuIcon = document.querySelector('.mobile-menu');
        const navMenu = document.querySelector('.nav-menu');

        menuIcon.addEventListener('click', () => {
            navMenu
                .classList
                .toggle('show');
        });
    </script>
    </body>
</html>

<footer>

하단에 작성자, 저작권 정보 관련 정보 작성

 

<script>

모바일에서 토글을 숨겼다가 보여지게끔 하기 위해서 자바스크립트 코드 추가함.

 

 

🟡 scss 코드

🔽 전체보기

더보기

@charset "UTF-8";

/* 전체 스타일 */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 글자 기본 */
body {
    font-family: Arial, sans-serif;
    font-size: 16px;
    line-height: 1.5;
    color: #333;
}

h1,
h2,
h3 {
    font-weight: bold;
    margin-bottom: 1rem;
}

p {
    margin-bottom: 1rem;
}

/* Header */
header {
    background-color: #f2f2f2;
    padding: 1rem;
    border-bottom: 1px solid #ccc;

    .container {
        display: flex;
        justify-content: space-between; //메인축 방향으로 아이템 정렬
        align-items: center;

        h1 {
            font-size: 2rem;
        }

        nav {
            display: flex;
            float: right;

            ul {
                list-style: none;

                li {
                    display: inline-block;
                    margin-left: 20px;

                    a {
                        text-decoration: none;
                        color: #333;

                        &:hover {
                            color: #2ecc71;
                        }
                    }
                }
            }
        }
    }
}


/* Main */
main {
    display: flex;
    flex-wrap: wrap;
    padding: 1rem;

    section {
        flex: 2;
        margin-right: 1rem;

        article {
            background-color: #f2f2f2;
            padding: 1rem;
            margin-bottom: 1rem;

            h2 {
                margin-bottom: 0.5rem;
            }

            p {
                margin-bottom: 1rem;
            }

            a {
                color: #333;
                text-decoration: none;
                font-weight: bold;
            }
        }
    }

    aside {
        flex: 1;
        background-color: #f2f2f2;
        padding: 1rem;

        h2 {
            margin-bottom: 0.5rem;
        }

        p:last-child {
            margin-bottom: 0;
        }
    }
}

/* Footer */
footer {
    background-color: #333;
    color: #fff;
    text-align: center;
    padding: 1rem;
}







/* 반응형 */

// 최대 너비 설정
@media screen and (max-width: 415px) { //iPhone XR 기준
    .container {
        flex-direction: column;
    }
    h1 {
        margin-bottom: 1rem;
    }

    .mobile-menu {
        display: block;
        span {
            display: block;
            width: 20px;
            height: 2px;
            background-color: #555;
            margin: 5px auto;
        }
    }

    main {
        display: flex;
        flex-direction: column;
        align-items: center;
    }
}


/* 모바일 용 네비게이션 메뉴 */

// PC화면에서 네비게이션 숨기기
@media screen and (min-width: 415px) {
    .nav-menu {
        display: flex;
        justify-content: flex-end;
        width: 100%;
        margin: 0;

        ul {
            display: flex;
            list-style: none;
            margin: 0;
            padding: 0;
        }

        li {
            margin-left: 30px;

            a {
                color: #555;
                text-decoration: none;

                &:hover {
                    color: #000;
                }
            }
        }
    }
}

// 화면 작아지면 네비게이션 아이콘 나타나기
@media screen and (max-width: 415px) {
    // 햄버거모양 네비게이션 아이콘
    .mobile-menu {
        display: block;
        position: absolute;
        top: 10px;
        right: 20px;
        width: 30px;
        height: 30px;
        background-color: #fff;
        border: 1px solid #555;
        border-radius: 50%;
        text-align: center;
        line-height: 28px;
        cursor: pointer;

        span {
            display: block;
            width: 20px;
            height: 2px;
            background-color: #555;
            margin: 5px auto;
        }
    }

    // PC 메뉴는 지우고
    .nav-menu {
        display: none;
    }
    // nav-menu show 가 되면 토글 클릭하면 보여지기
    .show {
        display: block;
    }

    // 모바일용 메뉴 나오기
    .mobile-nav {
        position: absolute;
        top: 60px;
        right: 20px;
        background-color: #fff;
        border: 1px solid #555;
        border-radius: 5px;
        padding: 10px;
        box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
        z-index: 1;

        ul {
            list-style: none;
            margin: 0;
            padding: 0;
        }

        li {
            margin-bottom: 10px;

            a {
                color: #555;
                text-decoration: none;

                &:hover {
                    color: #000;
                }
            }

        }
    }
}

 

🟨 구조 분석

 

기본 설정

@charset "UTF-8";

/* 전체 스타일 */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

/* 글자 기본 */
body {
    font-family: Arial, sans-serif;
    font-size: 16px;
    line-height: 1.5;
    color: #333;
}

h1,
h2,
h3 {
    font-weight: bold;
    margin-bottom: 1rem;
}

p {
    margin-bottom: 1rem;
}

*

전체선택자로 모든 현태의 요소를 선택함.

 

 

box-sizing : 요소의 너비와 높이 계산 방법

box-sizing: content-box;
box-sizing: border-box;

box-sizing: content-box; 는 콘텐츠 상자의 너비만을 고려해서 border나 padding을 고려하지 않아 부모 컨테이너에서 넘칠 수 있다.

box-sizing: border-box; 는 요소의 너비와 높이에 대해 부모 컨테이너에 넘치지 않도록 border나 padding을 고려한다.

 

 

line-height : 줄높이

line-height

텍스트 줄 간격

normal 은 브라우저의 기본값으로 1.2에 해당함.

1.0은 100%를 의미하며, em, px 등으로도 설정 가능하다.

 

 

margin / border / padding : 여백

[ margin ]

한 요소의 주위 여백으로 주변 요소와 거리를 두기 위해 쓴다. object와 나머지 요소와의 외부 여백.


margin-top (상단 여백)
margin-right (오른쪽 여백)
margin-bottom (아래 여백)
margin-left (왼쪽 여백)

* px, cm, % 가능.

padding과 다르게 음수값으도 지정 가능(예: -10px)

 

table {

margin: 5px 7px 3px 0px;    (위, 오른쪽, 아래, 왼쪽 순임)

}

 

[ border ]

contents(내용)을 감싸는 테두리로, 굵게하면 contents를 감싼 테두리가 두꺼워진다.

 

[ padding ]

contents(파란부분)과 테두리(border)사이의 여유공간. 즉, object 내의 내부 여백.

 

 

💡 border 까지가 요소이고, margin은 요소 주위의 여백이다.

💡 padding을 늘리면 박스가 커지고 margin을 늘리면 박스와 박스 사이 거리가 멀어진다.

 

 

 

px / em / rem : 폰트 단위

 

px : 모니터에 따라 다르긴 하지만 절대적인 폰트의 크기를 설정한다.

pt : 포인트 약자로, 문서에서 사용하는 사이즈

% : 기본 글꼴 크기에 대해 상대적인 값

em : 설정된 글꼴의 크기를 1em으로 놓고 상대적으로 계산한 것.(지정크기가 없다면 부모 요소 상속)

rem : 최상위(root) 요소인 html의 폰트 사이즈를 1em으로 놓고 상대적으로 계산한 것

 

💡 일반적인 폰트 사이즈가 16px이기 때문에 대충 1 rem = 16px정도로 본다.

💡 보통 기본 폰트 값(16px)을 바꾸어 사용하기 때문에 반응형 대응을 위해 rem을 많이 사용한다.

💡 여기서는 모바일과 pc의 폰트 사이즈를 다르게 하기 위해 사용함.

💡 최근 브라우저에서 zoom 기능을 다 지원하기 때문에 그냥 px로 박아도 무방하긴 하다.

 

 

header

/* Header */
header {
    background-color: #f2f2f2;
    padding: 1rem;
    border-bottom: 1px solid #ccc;

    .container {
        display: flex;
        justify-content: space-between; //메인축 방향으로 아이템 정렬
        align-items: center;

        h1 {
            font-size: 2rem;
        }

        nav {
            display: flex;
            float: right;

            ul {
                list-style: none;

                li {
                    display: inline-block;
                    margin-left: 20px;

                    a {
                        text-decoration: none;
                        color: #333;

                        &:hover {
                            color: #2ecc71;
                        }
                    }
                }
            }
        }
    }
}

 

display : 요소를 어떻게 보여줄 것인지?

 

none : 화면에서 보이지 않고 크기도 차지하지 않음.
block : 블록 박스, div가 갖는 기본값으로 width가 자신의 컨테이너의 100%이다. 즉, 가로 한줄을 다 차지함.
inline : 인라인 박스, 컨텐츠를 딱 감쌀정도의 크기만 갖는다. 줄바꿈이 안되고 요소의 크기만큼만 너비가 생성됨.
inline-block : block과 inline의 중간 형태, inline처럼 생성되지만 block처럼 너비 지정도 가능하다.

 

display와 box model의 관계

display  width   height   margin   padding      border    
block
inline X X 좌/우만 ㅇ(의미x) ㅇ(의미x)
inline-block

 

💡 inline은 height가 없기 때문에 padding이 먹긴 하지만 부모와 안겹치게 둘 수 있는 방법이 없다. 따라서 상/하는 요소 배치에서 설정하는 의미가 없음.

 

 

🎈 display : flex

참고 링크 :https://studiomeal.com/archives/197

display:flex

display:flex는 레이아웃 배치 전용 기능으로, 세로형 inline으로 보면 된다.

보통 가로 방향으로 여러 요소를 각각의 너비만큼 설정할 때 사용한다.

 

inline-flex

inline-flex 는 inline-block 처럼 요소의 높이와 너비를 설정할 수 있다.

flex-direction

flex-direction 는 배치 방향을 설정한다. row는 가로, colum은 세로, reverse는 반대로 정렬한다.

 

💡 크기가 작은 모바일 기기에서 column으로 배치하다가 일정 폭 이상이 되면 row로 바꿔주는 식으로 반응형 레이아웃을 구현할 수도 있다.

 

 

flex-wrap

flex-wrap 으로 줄넘김 처리를 할 수 있다.넘어가면 어디로 넘어갈지 설정한다.

justify-content

justify-content 는 메인축(가로 x축)의 아이템 정렬을 설정한다.

 

flex-start : 아이템을 시작점으로 정렬(기본값)

flex-end : 아이템을 끝점으로 정렬(좌 또는 우)

center : 아이템을 가운데로 정렬

space-between : 아이템을 좌우정렬하고 사이에 균일한 간격을 주어 정렬

space-around: 아이템의 좌우 전부에 균일한 간격을 주어 정렬

space-evenly: 아이템의 사이에 균일한 간격을 주어 정렬

💡 space-evenly는 IE와 Edge에서 사용 불가.

 

justify-content

align-items 는 수직축(세로 y축)의 아이템 정렬을 설정한다.

 

stretch : 아이템들이 수직축 양 끝까지 쭉 늘어난다.

flex-start : 아이템을 시작점으로 정렬(위나 아래)

flex-end : 아이템을 끝점으로 정렬

center : 아이템을 수직축 가운데로 정렬

baseline : 텍스트의 베이스라인 기준으로 정렬(글자 기준 정가운데만큼만)

baseline

 

 

align-content : space-between

align-content flex-wrap: wrap;이 설정된 상태에서, 아이템들의 행이 2줄 이상 되었을 때의 수직축 방향 정렬을 설정한다.

A와 B가 같이 있고 C가 wrap으로 넘어갔을 때 두 요소의 배치 방법임.

 

flex-start : 아이템을 시작점으로 정렬(기본값)

flex-end : 아이템을 끝점으로 정렬(좌 또는 우)

center : 아이템을 가운데로 정렬

space-between : 아이템을 좌우정렬하고 사이에 균일한 간격을 주어 정렬

space-around: 아이템의 좌우 전부에 균일한 간격을 주어 정렬

space-evenly: 아이템의 사이에 균일한 간격을 주어 정렬

💡 space-evenly는 IE와 Edge에서 사용 불가.

 

 

 

이어서 작성 예정...

반응형
LIST

댓글