본문 바로가기

FrontEnd

가장 일반적이며 기초적인 CSS 문제와 해결 방법 [번역]

반응형

원문 링크 : https://www.smashingmagazine.com/2018/12/common-css-issues-front-end-projects/

 

Common CSS Issues For Front-End Projects — Smashing Magazine

Rendering and interaction have become a lot more consistent across browsers in recent years. It’s still not perfectly uniform, however, and a lot of small issues can trip you up. A list of common issues along with their solutions.

www.smashingmagazine.com

1. Button과 Input 요소의 배경 Reset

크롬과 사파리의 인풋, 버튼 기본 스타일은 다르기 때문에 초기화해 줍니다.

브라우저 기본 스타일이 버튼 기본 디자인에 미치는 영향

button, input {
  appearance: none;
  background: transparent;
  /* Other styles */
}

2. Overflow : scroll vs auto

윈도우 크롬에선 overflow: scroll-y를 설정 시,  항상 수직 스크롤 막대가 보입니다.

(맥 크롬은 스크롤이 필요할 때만 보임)

맥과 윈도우 크롬의 비교

일관적인 동작을 위해선 overflow-y: auto를 적용합니다.

.element {
    height: 300px;
    overflow-y: auto;
}

3. flex-wrap 속성 추가

display: flex를 추가하면 요소가 플렉스 컨테이너처럼 동작하도록 할 수 있습니다.
하지만 화면 크기가 줄어들면 flex-wrap이 추가되지 않은 경우 브라우저에 가로 스크롤 막대가 표시됩니다.

<div class="wrapper">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
</div>
.wrapper {
  display: flex;
}

.item {
  flex: 0 0 120px;
  height: 100px;
}

위 경우 큰 화면에선 문제가 없지만, 모바일에서는 수평 스크롤 바가 보이게 됩니다.

왼쪽의 경우 원하지 않게 스크롤이 생기게 됨

해결책은 매우 쉽습니다. 공간이 충분하지 않으면 줄바꿈 하도록 합니다.
.wrapper {
    display: flex;
    flex-wrap: wrap;
}

4. 플렉스 아이템 갯수가 동적일 때 justify-content:space-between을 사용하지 마세요

justify-content: space-between이 플렉스 컨테이너에 적용되면 요소를 분배하면서, 요소 사이에 동일한 양의 공간을 남깁니다.
아래 예에는 8개의 카드 항목이 있으며 딱히 문제가 없어 보입니다.

8개의 항목을 포함한 플렉스박스


그런데 7개가 되면 어떻게 될까요?

7개를 포함한 플렉스박스, 간격이 일관되지 않음

가운데 정렬이 목적일 경우 justify-content: center를 사용하는게 나을 것입니다.
아니면 grid를 사용하세요


5. 긴 링크와 긴 단어

모바일 화면에서 기사를 볼 때 긴 단어나 긴 인라인 링크로 인해 가로 스크롤 막대가 나타날 수 있습니다.
CSS의 word-break를 사용하면 이러한 일이 발생하지 않습니다.

모바일 화면에서 기사를 볼 때 긴 단어나 긴 인라인 링크로 인해 가로 스크롤 막대가 나타날 수 있습니다.
.article-content p {
    word-break: break-all;
}​

단어 중간이 쪼개져 문제가 해결됨

자세한 내용은 CSS-Tricks 아티클을 확인하세요.

6. 투명 그라데이션

시작점과 끝점이 투명한 그라디언트를 추가하면 Safari에서 검게 보입니다.
Safari가 키워드 transparent를 인식하지 못하기 때문입니다.
이 키워드를 rgba(0, 0, 0, 0)로 대체하면 예상대로 작동합니다. 
위는 크롬, 아래는 사파리

아래 CSS를

.section-hero {
  background: linear-gradient(transparent, #d7e0ef), #527ee0;
  /*Other styles*/
}

아래 CSS로 교체하세요

.section-hero {
  background: linear-gradient(rgba(0, 0, 0,0), #d7e0ef), #527ee0;
  /*Other styles*/
}

7. Grid의 auto-fit과 auto-fill에 대한 오해

CSS 그리드의 refeat 함수는 미디어 쿼리를 사용하지 않고도 반응형 열 레이아웃을 만들 수 있게 해줍니다.
이를 달성하려면 auto-fill 또는 auto-fit을 사용하십시오.

.wrapper {
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}

(위)Auto Fill과 (아래)Auto Fit

  • auto-fill는 너비를 확장하지 않고 열을 정렬합니다.
  • auto-fit은 빈 열이 있는 경우 너비를 0으로 축소합니다.

이 주제애 대한 훌륭한 기사(excellent article)가 있습니다.


8. 뷰포트 높이가 충분하지 않을 때, 요소를 화면 상단에 고정하기

요소를 화면 상단에 고정했을 때, 뷰포트의 높이가 충분하지 않으면 어떻게 될까요?
단순합니다. 화면을 항상 채우고 있어서 화면에 보이는 영역이 작아 사용자가 불편함을 느끼게 됩니다.
뷰포트가

뷰포트의 높이가 500픽셀 이상인 경우에만 헤더를 상단에 고정하도록 브라우저에 지시합니다.

@media (min-height: 500px) {
    .site-header {
        position: sticky;
        top: 0;
        /*other styles*/
    }
}

(sticky 박스의 부모 박스가 scroll 박스를 벗어나면 sticky 박스는 다시 일반적인 흐름에 따릅니다.)
position: sticky를 사용할 땐, top 속성을 지정해야 합니다. 없으면 동작하지 않습니다.


9. 이미지에 max-width 설정하기

이미지를 추가할 때 max-width: 100%를 설정하세요.
화면이 작을 때 이미지 크기가 조정됩니다.
그렇지 않으면 브라우저에 가로 스크롤 막대가 나타납니다.

img {
    max-width: 100%;
}

10. main과 aside에 CSS Grid 사용

main과 aside 영역은 grid를 사용하기 가장 적절한 부분입니다.

이 경우 aside 영역의 높이는 항상 main의 높이와 동일합니다.

 

이 문제를 해결하려면 높이가 확장되지 않도록 aside 요소를 부모 요소의 시작 부분에 정렬합니다.
align-self 를 사용하면 됩니다.

.wrapper {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  grid-gap: 20px;
}

/** align-self will tell the aside element to align itself with the start of its parent. **/
aside {
  grid-column: 1 / 4;
  grid-row: 1;
  align-self: start;
}

main {
  grid-column: 4 / 13;
}

위: 높이가 확장됨, 아래 : 높이가 확장되지 않음


11. SVG에 fill 속성 사용

fill 속성이 SVG에 인라인으로 추가된 경우 예상대로 동작하지 않습니다.

 

예를 들어 인라인 fill 속성이 있을 경우,

아래와 같은 css는 동작하지 않습니다.

.some-icon {
    fill: #137cbf;
}

 

이 문제를 해결하려면 SVG의 인라인 fill 속성을 제거하거나

fill: color을 재정의합니다.

.some-icon path {
    fill: #137cbf;
}

12. 가상 요소 다루기

저는 가능할 때마다 의사 요소를 사용하는 것을 좋아합니다.
가상 요소(pseudo-elements)은 HTML을 변경하지 않으며 단지 장식 목적인 가짜 요소를 만드는 방법을 제공합니다.

 

보통 두가지 중 하나를 수행하는 것을 까먹습니다.

  • content : "" 추가하기
  • display 속성 없이 width, height 적용

아래 예에는 가상 요소로 추가되는 뱃지가 있습니다.

  • content: "" 속성을 추가해야 합니다.
  • 너비와 높이가 예상대로 작동하려면 요소에 display: inline-block을 적용해야 합니다.

가상 요소를 정상적으로 적용하는 모습


13. display: inline-block을 사용할 때 이상한 space

둘 이상의 요소를 display: inline-block 또는 display: inline으로 설정하면 각 요소 사이에 작은 공간이 생깁니다.
브라우저가 인라인 요소를 단어로 해석하고 각 요소 사이에 문자 공백을 추가하기 때문입니다.

 

아래 예에서 각 항목의 오른쪽에 8px의 마진을 적용하였지만
display: inline-block을 사용하여 공간 너비는 12px가 됩니다.

li:not(:last-child) {
  margin-right: 8px;
}

원치 않는 너비

간단한 수정 방법은 부모 요소에서 font-size: 0을 설정하는 것입니다.
그리고 자식 속성에서 font-size를 재정의 합니다.

ul {
    font-size: 0;
}

li {
    font-size: 16px; /*The font size should be reassigned here because it will inherit `font-size: 0` from its parent.*/
}
원하는 대로 설정된 마진

14. label 요소 for 속성으로 input id 할당 

양식 요소를 작업할 때 모든 레이블 요소에 할당된 ID가 있는지 확인하세요.
이렇게 하면 접근성을 높일 수 있으며 클릭하면 연결된 입력이 포커싱 가능합니다.

<label for="emailAddress">Email address:</label>
<input type="email" id="emailAddress">

더 나은 input 접근성


15. 대화형 요소에 폰트가 적용되지 않는 경우

전체 문서를 위한 폰트 스타일을 할당할 때 input, button, select 및 textarea와 같은 요소에는 폰트가 적용되지 않습니다.
브라우저가 디폴트 시스템 글꼴을 적용하기 때문에 디폴트로 폰트를 상속하지 않습니다.

이 문제를 해결하려면 폰트 속성을 수동으로 할당합니다.
input, button, select, textarea {
  font-family: your-awesome-font-name;
}

16. 수평 스크롤 바

일부 요소는 해당 요소의 너비로 인해 원하지 않는 가로 스크롤 막대가 나타납니다.
이 문제의 원인을 찾는 가장 쉬운 방법은 CSS outline를 사용하는 것입니다.
아래 스크립트를 이용해 찾아봅니다.(출처 : script)
[].forEach.call($$("*"), function(a) {
  a.style.outline =
    "1px solid #" + (~~(Math.random() * (1 << 24))).toString(16);
});
 
outline으로 너비가 생각보다 큰 요소 찾기

17. 눌리거나 펼쳐진 이미지

CSS에서 이미지 크기를 조정할 때

종횡비가 이미지의 너비 및 높이와 일치하지 않으면

이미지가 눌리거나(compressed), 늘어날(stretched) 수 있습니다.

 

해결책은 간단합니다.
object-fit을 사용하세요.
background image를 위한 속성인 background-size: cover와 유사합니다.

img {
    object-fit: cover;
}

눌린 이미지 vs object-fit 사용

물론 object-fit을 사용하는 것이 모든 경우에 완벽한 솔루션은 아닙니다.
일부 이미지는 자르거나(cropping) 리사이징(resizing)하지 않은 원본을 보여줘야 하며,
일부 플랫폼에서는 사용자가 정의된 크기로 이미지를 업로드하거나 자르도록 합니다.
예를 들어 Dribbble은 800 x 600픽셀의 썸네일 업로드를 허용합니다.

18. input에 적절한 type 추가하기

input에 적절한 type을 추가하세요
사용자 경험을 향상시키고, 접근성을 높일 수 있습니다.

<form action="">
  <p>
    <label for="name">Full name</label>
    <input type="text" id="name">
  </p>
  <p>
    <label for="email">Email</label>
    <input type="email" id="email">
  </p>
  <p>
    <label for="phone">Phone</label>
    <input type="tel" id="phone">
  </p>
</form>
input type에 따른 모바일 동작 변화

19. 오른쪽에서 왼쪽으로 쓰는 언어를 사용할 때 핸드폰 번호

오른쪽에서 왼쪽 레이아웃(right-to-left layout;rtl)으로 + 972-123555777과 같은 전화번호를 추가하면
더하기 기호가 번호 끝에 위치합니다.

이 문제를 해결하려면 전화번호 방향을 재정의 합니다.

(핸드폰 번호는 항상 ltr이기 떄문)

p {
    direction: ltr;
}

핸드폰 번호는 항상 ltr

반응형