상세 컨텐츠

본문 제목

[CSS] CSS가 괴로운 개발자를 위하여

프론트엔드

by Helia-17 2024. 1. 21. 23:53

본문

 

개발자들이 싫어하거나 괴로워하는 작업을 꼽으라면 유독 CSS 작업이 많이 나온다. 프론트엔드 개발자 중에는 내가 입력한 것이 곧바로 구현되는 것에 효용감을 느끼는 사람도 많지만, 다른건 좋아도 CSS만큼은 도무지 괴롭다는 사람들도 있다.

 

 

내 마음대로 되지 않는 CSS..

 

 

나는 시각적인 것을 좋아해서 멋있는 CSS 작업을 보면 북마크에 저장해두고 마는 개발자이지만, 마음대로 되지 않는 CSS에 괴로워했을 때도 많았다. 그런데 인턴으로 근무했을 때 온보딩 작업물을 테크리더 분께서 피드백해주시면서, CSS의 의미를 이해하고 규칙을 세워 작성할 수 있게 되었다. 그로 인해 거부감이나 막연한 두려움은 사라졌다. 물론 아직 더욱 노력해야겠지만, 당시 배워서 현재까지 잘 쓰고 있는 팁들을 공유해보려고 한다. 우선 테크리더 분이 설명해주셨던 것을 공유하고, 이후 내가 세운 규칙을 공유해보려고 한다. 

 

 

오남용하기 쉬운 CSS by 테크리더님

 

프론트엔드 인턴으로 근무할 당시 온보딩 작업물을 이예찬님(링크드인)께 리뷰받은 내용을 공유한다.

 

 

가장 눈에 띄는 오류가 소위 css로 그림을 그리는 일이다. 이게 무슨 소리냐면, 의미가 아니라 모양을 맞추기 위해 css속성을 오용하거나 남용하는 경우를 말한다. 나는 HTML이 문서의 의미를 담는 것이라면 CSS는 디자인의 의미를 담는 것이라고 생각한다.

 

의미 없이 모양만 맞추기 위해 CSS를 작업하면 틀림없이 다양한 경우에서 문제가 생긴다.

예컨대, 어떤 컨테이너 요소에 대해 우연히 정사각형으로 디자인 된 것만 보고 비슷하게 border-radius를 퍼센트 단위로 맞췄다고 하면, 그 콘텐츠가 넘쳐서 랩이 일어나는 바람에 정사각형이 깨지게 되면 border-radius 가 엉망이 돼서 길쭉하게 늘어진다.

그리고 위치 잡는데에 퍼센티지 단위를 쓰면 부모 요소 너비가 달라졌을 때 위치도 의도한 대로 안 나오게 된다.

 

그래서 CSS 작업은'잘 만들어진' 디자인을 디자인이 '의도한 대로' 구현하는 게 정말 핵심이다.

예컨대 컨테이너에 버튼 세 개가 가로로 나란히 배열 돼 있으면 그 사이 간격이 그냥 37px인지, 아니면 이 컨테이너 너비에서 버튼 사이를 골고루 띄워 두었더니 37px이 나온건지 이해하고 코딩 해야 한다. 레이블과 인풋이 가로로 있을 때 인풋이 고정 너비인건지 아니면 레이블 영역을 고정으로 두고 컨테이너의 나머지를 가득 채우는지 이해하고 코딩 해야 한다. 이 여백이 마진인지 패딩인지, 어디까지 마진이고 어디까지 패딩인지 이해하고 코딩 해야 한다.

 

문제는 '잘 만들어진' 디자인은 그걸 고려하고 만드는데, 초보 디자이너가 하는 실수가 이와 비슷하게 디자인으로 그냥 예쁘게 그림을 그려놓는 경우. 그리드 없이 디자인 하거나, 형식적으로 맞춰두거나, 콘텐츠가 늘거나 줄었을 때에 대한 대응이 안 돼 있거나, 의미 부여를 제대로 해두지 않아서 여러 반응형 케이스에 대응이 안 되거나... 그런 의미에서 피그마의 오토 레이아웃 기능이 참 좋다. 의미 부여하기 편하다.

 

💡 css의 모든 속성들은 의미가 있어야 한다. 그 의미를 곱씹어서 필요를 판단하며 작성하자.

 

 

흔히 CSS 코드 리뷰 할 때 개인적으로 냄새가 날 것 같은 코드

  • width: 100% 혹은 height: 100%, height: 100vh
  • position 속성
  • z-index 속성
  • 단위로 퍼센티지 사용
  • overflow: hidden

(이걸 쓴다고 나쁜건 아니고, 오남용의 경우가 많다는 것.)

 

추가 설명

[width: 100%]

  • 많은 경우 display: block 요소일테니 일단 쓸 일이라면 조금 특이한(?) 경우일 것
  • margin이 적용 된 경우 100%를 걸어주면 margin만큼 overflow 된다.

[height: 100%]

  • 조상 요소에 height 없어서 아무 효과도 없었다에 한 표
  • 뭔가 이걸로 시도했는데 잘 안 돼서 없애도 되는 코드 그대로 뒀다에 한표
  • 어쩌다 부모 요소에 height가 들어가면 깨질 수 있음

[overflow: hidden]

  • overflow: hidden같은 경우는 자식 요소들, 그중에서도 특히 툴팁이나 팝오버, 그리고 자식의 그림자가 잘려버릴 수 있어서 유의해야 하고, overflow: hidden이 그냥 튀어나오는 걸 안 보이게 하는 것 뿐만 아니라 레이아웃에 영향을 주기도 해서 유의해야 한다

 

위의 속성들을 아예 사용하지 말라는 것은 아니다. 중요한 것은 원하던 것이 잘 안돼서 이것저것 속성을 넣었다가 정확히는 모르겠지만 원하던 화면이 나타났을 때 "됐다!" 하고 넘어가면 안된다는 것이다.

 


 

내가 CSS를 작성하는 방식 by Helia

 

레이아웃을 위해 컴포넌트의 높이나 너비를 지정하는 것을 지양한다.

  • 기본적으로 height와 width를 주면 재사용성이 너무 떨어진다.
    • container를 사용하면 width를 쓸 필요가 없다. 전체적인 컨테이너를 잡고 margin-left: auto; 와 margin-right: auto; 또는 margin: 0 auto;로 정렬하는 방법을 권장
    • max-width, margin-left, margin-right를 사용하자.
    • 이렇게 하면 자식에게 영향이 가지 않는다.
  • 부모 컴포넌트의 margin을 통해 자식컴포넌트가 자연스럽게 남는 부분을 차지하도록 한다.
    • width: 95%, max-height: 80%;등의 애매한 수치를 지양한다.
    • margin을 이용하면 자식 컴포넌트가 이동하더라도 의도와 다르게 공간을 차지하는 것을 막을 수 있고, 부모 컴포넌트에 다른 자식 컴포넌트가 들어오더라도 동일한 레이아웃을 구현할 수 있다.
    • 레이아웃을 위해 자식 컴포넌트에서 margin마이너스 값을 사용할 수도 있다.

삭제 기능의 휴지통 아이콘은 absolute로 댓글 테두리 바깥에 있는 UI를 구현할 수도 있지만, margin의 마이너스 값을 사용하게 되면 댓글의 맥락에 벗어나지 않는다는 의미를 주면서도 원하는 UI를 만들 수 있다.

  • width를 다 해제하고 margin-right: -37px ← 이때의 수치는 유의미한 값이므로 OK
  • 자식 컴포넌트가 늘어나는 것을 의도할 경우 flex-grow:1;을 권장
    • flex: 1 1 auto
      • flex-grow: 1
      • flex-shirink: 1
      • flex-basis: auto
  • margin과 padding의 구분
 💡 내가 이만큼 공간을 확보하고 싶어! → 방어적인 느낌의 padding
💡 내가 이만큼 떨어지고 싶어! → 주체적인 느낌의 margin
  • 높이는 특별한 의도가 없다면 지정하지 않는다.
    • 기본적으로 문서이다. 문서의 내용을 감싸는 역할로 div를 사용하는 것이다.
    • 높이를 지정하는 것보다 안의 내용에 따라 높이가 변하도록 하는 것이 자연스럽다.
    • 따라서 높이를 주게되면 문서의 내용이 변했을 때 대응하기가 어렵다.
    • height를 주기보다 마진을 주는 방식을 사용하자.
    • 특정 영역 안에서 스크롤 되도록 하고 싶다 등의 의도가 있는 경우 부모 컴포넌트에서 레이아웃을 다 잡아두고 max-height:100%;를 사용한다. 이와 함께 overflow-y: auto;를 사용하는데, 내용이 없을 때는 스크롤이 사라지므로 scroll보다 낫다고 할 수 있다.

 

가운데 정렬만을 위해 flex를 사용하지 않는다.

  • 이미지와 h1같은 태그의 경우 둘다 text로 이루어져 있으므로 text-align: center;을 통한 가운데 정렬
  • margin-left: auto; margin-right: auto; == margin: 0 auto; 사용
    • 만약에 이 방법이 되지 않는다면
      • <!Doctype ~> 선언이 제대로 되었는지 확인해보아야 한다.
      • auto는 자동으로 사이즈를 설정해주기 때문에 가로폭의 사이즈를 정확히 인식할 수 있어야 정렬이 가능하다.
      • inline속성에는 적용되지 않는다 (span태그 등의 inline 속성은 자기 자신만큼의 영역값-width, height를 갖기 때문) ⇒ 해당 요소의 display 속성을 block으로 바꾸어주는 것도 해결 방법이다.

 

 

폰트가 커질 경우에도 대응 가능한 CSS를 작성한다.

input 레이아웃을 잡는다고 할때 display: block;(원래 inline이므로), width: 100%;, box-sizing: border-box;(input 창이 약간 넘치는 경우 해결할 수 있다. )의 속성에 더해 스타일링은 padding으로 주면 폰트가 갑자기 커져아 할 경우에도 사용 가능한 코드가 된다.

 

 

글자 수가 늘어났을 때도 레이아웃이 깨지지 않도록 한다.

여기서 username이 길어진다면? 또는 댓글이 더 길어진다면? 텍스트가 가려질 경우나 Y/N버튼과 좋아요 버튼이 겹치지 않는지 체크해야 한다. 생략하고 싶다면 말줄임표를 CSS 속성을 사용해야 한다. abbr 태그의 선택 속성인 title을 사용하면 전체 텍스트를 제공할 수 있다.

  • 여러 컨텐츠가 가로로 배열된 경우 특정 컨텐츠가 엄청 길어졌을 때도 레이아웃을 유지할 수 있는지를 고려하고, 이에 대응하거나 컨텐츠의 길이를 제한하는 기획을 추가해야 한다.

 

 

position 속성 사용을 지양한다 (필수 아님, 상황에 따라 다름)

  • 문서의 의미로 봤을때 크게 맥락에 벗어나는 요소가 아니라면 absolute 포지션 속성을 사용하지 않는다. 화면이 똑같이 보이더라도 margin을 줘서 레이아웃을 잡는지, 다른 방법으로 레이아웃을 잡는지에 따라 그 의미가 달라진다.
  • abolute보다 flex나 margin 사용을 권장한다.
    • 그러나 flex를 사용하면 좌, 우 요소 크기가 다를경우 중간이 정확히 중간에 위치하지 않을 수도 있다 → 자리잡아두는 용으로 div를 지정해두는 것 권장
  • 어쩔 수 없이 absoute요소를 사용한다면 다른 요소의 영역이 늘어나서 absolute와 겹치는 일이 없도록 계산해서 padding을 지정해둔다.

 

 

그 외..

  • overflow: hidden을 지양한다
  • z-index 속성을 지양한다 (필수 아님, 상황에 따라 다름)
  • 속성들은 다음과 같은 순서로 작성한다

 

체크리스트

  • 적절하게 CSS를 사용했는가?
  • 굳이 안써도 되는 CSS를 사용했는가?
  • 쉽게 사용했어도 될 CSS인데 어렵게 사용한 CSS가 있나?
  • 폰트 크기가 증가하거나, 특정 컨텐츠가 길어질 경우에도 대응할 수 있는가? (어떤 요소가 늘어날 지를 생각해 볼 것)
  • Mobile 까지 생각하고 CSS를 적용했나?
  • 함께하는 팀원도 사용하기 쉬운 CSS 속성인가?

관련글 더보기

댓글 영역