My Profile Photo

DongChanS's blog


수학과 학생의 개발일지


CSS와 Bootstrap으로 반응형 웹사이트 만들기

CSS파일의 패턴매칭(단축키)

CSS 파일은 여러 편리한 패턴매칭기능들이 있습니다.

/*모든 요소에 대해서 마진,패딩을 0으로 잡는게 편함 */
*{
    margin:0;
    padding:0;
}
/*다른 두 태그에 대한 css를 한꺼번에 지정 가능함*/
section,ul{
    margin: 10px 0px;
}
/*부모자식간의 관계에 대한 룰도 지정가능함*/
section>ul>li{
    font-size:20px;
    font-weight:bold;
}
/* a태그와 a태그 바로다음에 따라오는 ul태그 하나만 적용 */
a + ul {
    background-color:gold;
}
/* a태그와 a태그 바로다음에 따라오는 ul태그 전부 적용*/
a ~ ul {
    border : 1px solid gray
}
/* a태그 중에서 target 속성이 _self인 태그만 적용
target속성은 링크를 클릭할 때 창을 어떻게 열지 결정하는속성인데,
ex) _self : 현재 창에서 엶.. , _blank : 새 창에서 엶 ... */
a[target="_self"]{
    border : 1px solid darkgray;
    border-radius: 5px;
    background-color: white;
    padding: 5px;
}
/* alt속성이 TYPE 이거나, TYPE-___ 의 형식만 적용함.*/
img[alt|="TYPE"]{
    box-shadow:-1px -1px 3px black;
}
/* target속성이 _b로 시작하는 태그만 적용함
a태그는 기본적으로 inline인데 margin과 padding을 전부 다 먹이기 위해서 inline-block를 사용함 */
a[target^="_b"]{
    background-color: blue;
    display : inline-block;
    padding: 10px;
    margin: 30px;
    color: white;
}
/* href속성이 istj로 끝나는 태그만 적용함 */
a[href$="istj"]{
    background-color: green;
    color : white;
}
/* 가장중요!!! class속성에 "type을 포함"하고 있는 태그만 적용함 */
ul[class*="type"]{
    text-align: center;
    padding: 35px 0;
}
/* class속성에 type을 "독립적으로" 포함하고 있는 태그만 적용함 
ex) c-type (X) c type(O) */
ul[class~="type"]{
    border:1px dashed purple;
}

이런 패턴매칭은 정규표현식(regular expression)과 관련된 기호이다.


이걸 잘 알면 bootstrap의 css파일을 해독하는데 도움이 된다.

ex) col-2, col-3 col-4 이런 것들을 어떻게 한번에 해독하는지에 대해서 유추할 수 있음

.no-gutters>.col,.no-gutters>[class*=col-]{
    padding-right:0;
    padding-left:0
}
.form-row>.col,.form-row>[class*=col-]{
    padding-right:5px;
    padding-left:5px
}


@media print{
    *,::after,::before{
        text-shadow:none!important;
        box-shadow:none!important
    }
    a:not(.btn){
        text-decoration:underline
    }

: 는 수도클래스를 의미함(마우스를 가져다 댈 때만 반응) // not같이 부정문도 사용가능한걸 적용할 수 있음.


반응형 웹페이지 만들기

즉, 그리드 시스템은 모바일위주의 반응형 프로젝트이다.

부트스트랩을 잘 활용해서 반응형 웹페이지를 잘 만들어보자

ex)

<body>
    <div class="container">
        <div class="row">
            <div class="font-weight-bold text-center bg-primary col-4">col-1</div>
            <div class="font-weight-bold text-center bg-warning col-4">col-2</div>
            <div class="font-weight-bold text-center bg-success col-4">col-3</div>
        </div>
    </div>   
</body>
  1. 디바이스마다 적용되는 웹사이트를 미리보기로 볼 수 있다.

    기준으로 놔둔 폰들은 대체로 작은 폰들(큰 폰들은 왠만하면 문제없음, 작은 폰들이 문제임)

    이런 경우에는 계속 줄이면 폰트가 깨지니까 조금 분리했으면 좋겠음

    2

  2. sm : (상대적으로) 작은 디바이스까지는 각각 그리드 4개를 가지고, 그것보다 작아지면 그리드를 풀어버리고 12개를 가져간다. col-sm-4 기준에서는 575가 경계선이다.

    3

  3. 위에서 본 media쿼리는 Responsive breakpoint를 매기는 데 일조한다.

    https://getbootstrap.com/docs/4.2/layout/overview/

    // Extra small devices (portrait phones, less than 576px)
    // No media query for `xs` since this is the default in Bootstrap
       
    // Small devices (landscape phones, 576px and up)
    @media (min-width: 576px) { ... }
       
    // Medium devices (tablets, 768px and up)
    @media (min-width: 768px) { ... }
       
    // Large devices (desktops, 992px and up)
    @media (min-width: 992px) { ... }
       
    // Extra large devices (large desktops, 1200px and up)
    @media (min-width: 1200px) { ... }
    

    이런식으로 breakpoint를 직접적으로 선언할 수 있는데

    보통 breakpoint는 해당하는 디바이스 군의 최대규모를 커버하는 경우

    ex) small device는 최대 575px까지로만 생각하겠다.

      Extra small
    <576px
    Small ≥576px Medium ≥768px Large ≥992px Extra large ≥1200px
    Max container width None (auto) 540px 720px 960px 1140px
    Class prefix .col- .col-sm- .col-md- .col-lg- .col-xl-
    # of columns 12        
    Gutter width 30px (15px on each side of a column)        
    Nestable Yes        
    Column ordering Yes        

    Bootstrap의 클래스를 보면 이런 설정이 잘 녹아들어있다.

    @media (min-width:576px){
        .col-sm{
            -ms-flex-preferred-size:0;
            flex-basis:0;
            -ms-flex-positive:1;
            flex-grow:1;
            max-width:100%
        }
    
  4. 이것보다 조금 더 반응형으로 만들고싶다. (예시 사이트)

    ex) 6개의 칸

    큰 디바이스(1X6) -> 중간 디바이스(3X2) -> 작은 디바이스(6X1)

        <div class="container">
            <div class="row">
                <div class="font-weight-bold text-center bg-primary col-lg-2 col-md-4">col-1</div>
              	<!-- 이거 6개 있음 -->
            </div>
        </div>   
    

    클때는 col-2가 적용(각각 2개의 칸) 중간사이즈에는 col-4가 적용되는 방식으로 바꿀 수 있다.

  5. 이것뿐만 아니라 navbar같은 부트스트랩의 component들 모두 이러한 반응형 클래스를 사용가능하다.

    ex) .navbar-expand{-sm -md -lg -xl}

    즉 포맷을 가져올 때 md같은 옵션이 있으면 내맘대로 커스터마이징 가능하다.

    CSS중에서 상속되지 않는 속성이 있다?

그동안 모든 CSS의 속성이 상속되는줄 알았는데 안되는 것도 있었다고 한다.

출처 : https://poiemaweb.com/css3-inheritance-cascading

property Inherit
width/height no
margin no
padding no
border no
box-sizing no
display no
visibility yes
opacity yes
background no
font yes
color yes
line-height yes
text-align yes
vertical-align no
text-decoration no
white-space yes
position no
top/right/bottom/left no
z-index no
overflow no
float no

특히 어떤 부모태그 안에 이미지 태그를 집어넣으면

width와 height도 상속되지 않기 때문에 이미지가 삐져나올 수 있다.

예시) Bootstrap component의 modal component 안에 이미지 태그를 넣었다.

<div id="movie-1-modal" class="modal fade">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">내안의 그놈	The Dude in Me</h5>
            </div>
            <div class="modal-body">
                <img src = "assets/20176251-1.jpg", alt="...">
                <hr>
                <h3>줄거리</h3>
                <div>나 너니? 너 나니??
                    제대로 바뀐 아재와 고딩, 웃음 대환장 파티!
                    엘리트 아재 판수(박성웅)를 우연히 옥상에서 떨어진 고등학생 동현(진영)이 덮치면서 제대로 바뀐다. 
                    게다가 판수는 동현의 몸으로 첫사랑 미선(라미란)과 존재도 몰랐던 딸 현정(이수민)을 만나게 되는데… 
                    대유잼의 향연, 넌 이미 웃고 있다!</div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-dark" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

결과)

4

그런 문제를 해결하기 위해서는, 부모의 width, height를 따르게 특별한 조치를 취해줘야한다.

/* 부모 width의 100%만큼 받겠습니다 */
.modal-img {
    width : 100%;
}
/* 혹은 이렇게도 가능한데 잘 안쓰임 */
.modal-img {
    width : inherit;
}

수정된 결과)

5

width를 부모와 똑같이 줄였더니, height도 비율에 맞게 줄어든 모습을 확인할 수 있다.


Max-height, Min-height 프로퍼티

6

이렇게 카드 이미지들을 잘 만들었는데 컨텐츠의 길이에 따라서 최대 크기가 변하는 문제가 있다.

이런 문제를 해결하기 위해서, Max-height 나 Min-height를 이용해서 최소나 최대길이를 제한할 수 있다.

(Note: The value of the max-width property overrides width.)


마우스에 반응하는 이미지 만들기

7

마우스를 갖다대자마자 반응하면서 눈에 띄게 하는 기능을 만들고 싶다.

처음에는 이런 기능을 매우 간단하게 구현할 수 있는줄 알았지만 그렇지는 않았다.

4단계를 거쳐서 만들 수 있다.

  1. a태그 안에 이미지와 컨텐츠(텍스트, 보라색 배경)를 담을 태그를 만든다.
  2. a태그의 시작점과 컨텐츠의 시작점을 겹친다.
  3. 컨텐츠의 백그라운드와 이미지의 크기를 일치하게 한다.
  4. a태그에 마우스를 갖다댈 때만 백그라운드가 발현되게 한다.


첫번째)

<div class="best-item">
    <a href="#" class="d-block">
        <img src="assets/item-01.jpg" alt="인기상품1">
        <div class="best-item-content d-flex flex-column justify-content-end">
            <h3 class="best-item-title">상품 이름</h3>
            <p class="best-item-text">상품 정보</p>
        </div>
    </a>
</div>

d-flex flex-column justify-content-end 는 텍스트를 정렬하기 위해서 만들었습니다.


두번째) position property를 활용해서 위치를 동일시함.

.best-item a {
    position: relative;
}
.best-item-content {
    position : absolute;
    top : 0;
    left : 0;
    right : 0;
    bottom : 0;
    background-color : rgba(126,91,239,.8);
}


세번째) 여기는 상당히 복잡한데, 다음과 같은 step들로 나눠볼 수 있다.

  1. a태그를 inline이 아니라 block으로 만든다

    .d-block{
        display:block!important
    }
    

    왜 a태그를 block으로 만드냐면, a태그가 둘러싸여진 div태그의 크기를 받기 위해서이다.

    만약 inline이면 a태그 자체의 크기는 변하지 않기 때문에 a > div 태그의 크기에도 문제가 생기는 것이다.


    부트스트랩의 d-block 클래스는 display:block과 동일한데

    ! important라는 녀석은 적용의 우선순위를 최대로 하는 키워드이다.

  2. 이미지의 크기와 a태그 컨텐츠의 크기를 동일시한다.

    .best-item img {
        width : 100%; 
        height : auto;
    }
    

    이건 아까 배운 width와 height 프로퍼티를 적절히 조절해서 할 수 있다.


네번째) a태그에 마우스를 갖다댈때만 컨텐츠의 백그라운드가 발현

a태그에는 hover라는 pseudoclass가 있는데

이 hover라는 친구는 클릭될때만 발현되는 클래스라고 생각하면 된다.

즉, 평소에는 투명도를 0을 줘서 백그라운드를 없애고있다가, hover가 발현될때만 투명도 1을 주면 된다.

.best-item-content {
	opacity : 0;
}

.best-item a:hover .best-item-content{
    opacity : 1;
}
comments powered by Disqus