FrontEnd/CSS

[HTML & CSS] Google Clone (1) Flex Container, 로고, footer

hayjo 2021. 2. 21. 15:45

Google 페이지를 클론코딩하는 작업을 했다. 기능적인 부분은 무시하고 외양에만 집중했다.

분량 이슈로 나머지는 아래쪽에서 마무리했다.

2021/02/22 - [FrontEnd/Prep] - [HTML & CSS] Google Clone (2) 내비게이션, 검색


 

먼저 페이지를 Box 단위로 나누어 보았다.

 

 

큰 박스 6개가 제일 먼저 눈에 띈다.

위의 로그인 메뉴는 내비게이션인 것 같고, 로고는 아무 기능이 없는 그냥 로고 이미지, 중간의 검색창이 메인으로 보인다.

검색창 아래에는 현재 설정된 언어를 보여주는 부분이 나오고, 그 아래로 접속한 국가, 마지막으로 정보 및 약관 라인이 있다.

순서대로 nav, div, main, section, footer(div(접속국가), div(정보 및 약관) 태그로 구성하기로 한다.

 

 

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <nav>내비게이션</nav>
    <div class="logo">로고</div>
    <main class="search">검색</main>
    <section class="language">언어설정</section>
    <footer>
      <div class="location">접속국가</div>
      <div class="clauses">약관</div>
    </footer>
  </body>
</html>

 


[로고] margin: auto와 flexbox

로고 이미지가 제일 간단하니까 로고 이미지를 먼저 추가하기로 한다.

구글 홈페이지에 들어가서 이미지 주소를 복사해온 다음, 로고 부분에 추가해준다.

 

 

<div class="logo">
  <img class="logoImg" alt="Google" src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
</div>

 

 

로고가 무사히 추가되었으니 가운데 정렬을 해야한다. 개발자 도구에서 로고를 어떻게 정렬했는지 살펴보니,

 

 

부모태그에서 align-items: center를 주었다. align-items가 어떤 프로퍼티인지 MDN을 찾아보았다.

align-self 프로퍼티를 부모 수준에서 직계 자식들한테 실행하는 프로퍼티라고 한다.

flexbox에서는 교차축(flex축 반대축)에 요소들을 정렬하고, grid에서는 그리드 영역 내 블록축 안에서 요소를 정렬한다고 한다.

 

그대로 부모에게 display: flex와 align-items를 줘본다.

이동할 공간을 주기 위해서 height를 주고, 블록을 크기를 파악하기 위한 background-color도 주었다.

.logo {
	display: flex;
	flex-direction: row;
	align-items: center;
	height: 300px;
	background-color: lightgray;
}

 

 

flex축이 row니, 반대편인 column 방향으로 정렬되고 있다. flex-direction을 column으로 바꿔보니

 

 

row방향으로 정렬되는 걸 확인할 수 있다.

구글 홈페이지는 윈도우창의 세로 크기에 따라서 위의 회색 로고박스 크기가 달라지는데,

구글 로고는 회색 로고박스의 end부분 중앙에 위치하고 있다.

나도 따라서 flex-direction을 column으로 주고, 박스 내에서 로고의 위치를 바닥에 붙이는 속성을 찾아보았다.

위 img를 감싸고 있는 부모는 아래 프로퍼티를 가지고 있다.

min-height: 92px; /* 로고 이미지 높이 */
max-height: 290px;
height: 100%;
margin-top: auto;

div로 한 번 더 감싸고, 위의 프로퍼티를 적용해보니

<div class="logo">
  <div class="logoWrapper">
    <img class="logoImg" alt="Google" src="https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png">
  <div>
</div>

 

 

의도대로 바닥 중앙 정렬이 되었다! 궁금해서 왜 그런지 살펴보니 이런 글이 있다.

flexbox로 만들 수 있는 10가지 레이아웃의 3 - 브라우저 화면 아래에 붙는 푸터 부분에서,

flex item에 margin-top: auto 속성을 적용하면 바깥 여백이 flex item을 위쪽에서 아래쪽으로 민다고 되어있다.

flex item과 margin auto 키워드로 정보를 좀 찾아보니

css-tricks.com/the-peculiar-magic-of-flexbox-and-auto-margins/

사방 모두 auto margin의 반대로 정렬된다고 한다. css-tricks 포스트에서 참조한 아래 글에서

hackernoon.com/flexbox-s-best-kept-secret-bd3d892826b6

 

"If you apply auto margins to a flex item, that item will automatically extend its specified margin to occupy the extra space in the flex container, depending on the direction in which the auto-margin is applied."

"flex 요소에 auto margin을 주면, 해당 요소는 flex 컨테이너에서 auto-margin이 지정된 방향으로 추가 공간을 확보하기 위해서, 지정된 margin 값을 자동적으로 초과하게 된다."

 

방향을 명시하지 않으면 정중앙에 놓이게 되므로, 메인축에 하나 이상의 요소를 배치하는 방법이 된다고 한다.

margin: auto를 2개 이상의 flex item에 지정하면 flex 컨테이너에 justify-content: space-around를 준 것과 같다고.

그리고 auto margin을 쓰면 해당 요소가 메인축에서 점유할 수 있는 공간 전부를 마진이 먼저 가져가 버리기 때문에, text-align은 무용지물이 된다.

 

이 로고박스가 늘어나기는 하는데, 일정 수준까지만 늘어나고 멈춘다. flex Container의 프로퍼티를 찾아봐서, logo 클래스에 max-height: 290px;을 줬다.

이제 그 다음으로 컨텐츠가 적은 언어설정 부분을 만들어본다.

 

 


[언어설정] flex-grow, flex-shrink

이 부분도 위의 로고와 마찬가지로 flex다. 화면을 늘렸을 때, 로고박스는 최대 290px까지를 차지하고, 나머지 공감을 언어설정 파트가 가져간다.

컨테이너는 늘어나지만 컨테이너 상에서 텍스트(Google 제공 서비스: English)의 위치는 그대로여야해서 div로 한 번 더 묶어줬다.

 

 

<section class="language">
  <div class="langOption">
    Google 제공 서비스: <a>English</a>  
  </div>
</section>

 

먼저 텍스트 부분에 맞춰서 CSS를 주고

 

 

.langOption {
	font-size: small;
	font-family: arial,sans-serif;
	line-height: 28px;
	text-align: center;
}

.langOption a {
	color: #1a0dab;
	padding: 0 3px;
	text-decoration: none;
}

.langOption a:hover {
	text-decoration: underline;
    cursor: pointer;
}

부모로 가서 flex를 주려는데 부모의 display가 flex가 아니고 block다. 그리고 flex-grow: 1이라는 프로퍼티를 가지고 있다.

 

 

생각해보니 저 문구 부분은 고정된 위치에 있으니 flex될 게 없고, 이 문구를 감싸고 있는 공간 자체가 늘어나는 거니까

맨처음에 나눴던 박스 6개를 가진 부모가 flex Container여야 한다.

전체를 감싸는 div를 하나 추가해주고

<body>
  <div class="mainFlexer">
    <nav>내비게이션</nav>
    <div class="logo"></div>
    <main class="search">검색</main>
    <section class="language"></section>
    <footer>
      <div class="location">접속국가</div>
      <div class="clauses">약관</div>
    </footer>
  </div>
</body>

flex가 적용될 수 있도록 CSS를 주었다.

html, body {
  height: 100%;  /* 화면 전체를 점유 */
  margin: 0;
  padding: 0;
}

.mainFlexer {
  display: flex;
  flex-direction: column;
  height: 100%;  /* 얘도 화면 전체를 점유 */
}

.language {
  flex-grow: 1;  /* 늘어나라 */
  background-color: lemonchiffon;
}

 

 

 

화면에서 다른 요소들이 차지하는 부분을 빼고는 전부 점유하고 있음을 확인했다.

기본값이 0이라서 나머지 부분은 신경쓰지 않아도 될 것 같다.

flex-shrink는 이와는 반대로, flex-container가 flex-item 보다 작을 때, 크기를 줄일 건지를 설정하는 옵션이다.

화면 크기가 작아져도 저 텍스트 사이즈가 여기서 더 이상 줄어들면 안 되니까 flex-shrink: 0;을 준다.

 

이제 이 밑에 오는 footer를 만든다.

 

 


[footer] justify-content: space-evenly;  flex-wrap: wrap;

footer에는 접속국가 부분과 약관 부분이 있다.

 

 

약관은 다시 2부분으로 나뉜다. Google 정보 ~ 검색의 원리가 한 묶음이고, 개인정보처리방침 ~ 설정이 한 묶음이다.

각각은 a태그로 hover underline이 달려있다.

일단 기본적인 부분을 채워주고

<footer>
  <div class="location">
    대한민국
  </div>
  <div class="clauses">
    <div class="clausesWrapper">
      <a>Google 정보</a>
      <a>광고</a>
      <a>비즈니스</a>
      <a>검색의 원리</a>
    </div>
    <div class="clausesWrapper">
      <a>개인정보처리방침</a>
      <a>약관</a>
      <a>설정</a>
    </div> 
  </div>
</footer>

폰트, 색상, 배경색, 패딩을 맞춰줬다.

footer {
  background-color: #f2f2f2;
}

.location {
  padding: 15px 30px;
  border-bottom: 1px solid #dadce0;
  font-size: 15px;
  color: rgba(0,0,0,.54);
  font-family: arial,sans-serif;
}

.clauses {
  font-size: 14px;
  font-family: 'Apple SD Gothic Neo',arial,sans-serif;
  color: #222;
  padding: 0 20px;
}

.clauses a {
  padding: 15px;
  color: #70757a;
  text-decoration: none;
  cursor: pointer;
}
.clauses a:hover {
  text-decoration: underline;
}

 

 

접속국가 부분은 문제가 없는데, 약관 부분이 두줄로 나온다.

개발자도구에서 약관 ~ 설정을 감싸고 있는 div 태그를 살펴보니 justify-content: space-evenly; 속성이 부여되어 있다.

MDN을 보니 flex container의 메인축에 놓인 자식들이나, grid container의 inline(row) 축에 놓인 자식들을 어떻게 정렬할 것인지를 결정하는 속성이라고 한다.

다만 justify-content는 length와 auto margin이 적용된 뒤에 반영되므로, flexbox 레이아웃에서 flex-grow가 0이 아닌 자식이 있는 경우처럼, 특정 요소가 남은 공간을 이미 다 점유해버린 경우에는 효과가 없다고 한다.

 

justify-content 속성을 줘야 하니까 display: flex를 주고, justify-content: space-evenly를 줬다.

.clauses {
  /* 폰트 및 나머지 설정들 */
  display: flex;
  justify-content: space-evenly;
}

 

 

2줄인 문제는 해결 됐는데 a태그의 패딩 문제가 해결되지 않았다.

분명히 a에 padding: 15px가 들어가있는데 세로 패딩이 전혀 반영되지 않았다.

곰곰이 생각해보니 a는 inline 태그다. 당연히 세로 패딩이 반영될리가 없다.

a { display: inline-block; }을 줬더니

 

 

 

반영은 됐는데 실제 구글 페이지와 미묘하게 분할 상태가 다르다. 다시 개발자도구를 열어보니

 

 clausesWrapper에도 display: flex와 justify-content: space-evenly가 있다. 똑같이 반영해주니

.clausesWapper {
  /* 폰트 및 나머지 설정들 */
  display: flex;
  justify-content: space-evenly;
}

 

 

해결되었다. 화면이 작아서 위의 텍스트가 다 들어가지 않는 경우, 구글 페이지는 이렇게 두 줄로 표시되는데,

아무 설정 안 한 내 페이지는 한 블록의 넓이가 좁아진다. 이걸 해결하려면 clausesWrapper에 flex-wrap: wrap;을 주면 된다.

 

 

 

그러면 이렇게 되는데, 이건 clausesWrapper의 부모인 clauses에 flex-wrap: wrap;가 없기 때문이다.

clausesWrapper의 자식들은 두줄에 분배되었지만, clausesWrapper 자체는 clauses의 공간을 row 방향으로 나눠 갖고 있다.

 

 

.clauses {
    flex-wrap: wrap;
}

 

 

성공!