만족은 하되 안주하지는 말자

기록해야 기억한다

카테고리 없음

[vue] 스스로 만들어보는 To Do List - 3 : CSS 꾸미기

D36choi 2021. 12. 10. 15:35
728x90

https://github.com/d36choi/extodo/tree/feat/css

 

GitHub - d36choi/extodo: vue3.js To Do List 만들기

vue3.js To Do List 만들기. Contribute to d36choi/extodo development by creating an account on GitHub.

github.com

 

2021.10.31 - [프로그래밍/frontend] - [vue] 스스로 만들어보는 To Do List - 1

2021.11.06 - [프로그래밍/frontend] - [vue] 스스로 만들어보는 To Do List - 2 : Vuex 적용

 

 

현재 만든 기능은 매우 단순하다. 이번엔 웹페이지 답게, 조금이라도 보기 좋게 디자인할 수 있도록 필요한 플러그인이나 이론으로 간단하게 꾸며보도록 하고자 한다.

상세한 코드들은 위 저장소에서 확인할 수 있다.

목차

0. sass loader 를 설치하자

1. css flex를 익혀 사용해보자

2. fortAwesome 을 도입해 예쁜 아이콘을 추가해보자

3. google font를 추가하자

sass loader 설치

sass loader 를 설치하면. css 확장형 전처리기 (CSS Preprocessor) 인 sass, scss 를 사용할 수 있다.

browser는 css 만을 인식하지만 css 자체로는 워낙 오래된 양식이다보니 불편함을 감수하며 작성해나가야 한다.

개발자가 그 불편함을 덜어내고 효율적으로 스타일을 재구성할 수 있도록 해주는 것이 css 전처리기이다.

나는 scss를 통해 좀 더 계층적으로 css 코드를 작성할 수 있도록 해보려 했다.

먼저 아래 명령어로 필요한 확장을 설치해준다.

npm install --save-dev node-sass sass-loader

그 뒤 필요한 vue파일의 style 영역에 아래처럼 lang="scss" 를 추가해주면 아래 스타일에는 scss 방식으로 작성가능해진다.

<template>
  <div id="todolist">
    <div class="item" v-for="data in todos" :key="data.id">
      <div class="text">{{ data.content }}</div>
      <div :class="'period ' + data.period">
        {{ this.periods[data.period] }}
        <font-awesome-icon :icon="this.icons[data.period]" :color="this.colors[data.period]" />
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      periods: {dawn: '새벽', morning: '아침', afternoon: '낮', night: '저녁'},
      colors: {dawn: '#FFFFFF', morning: '#FFFFFF', afternoon: '#FFFFFF', night: '#000000'},
      icons: {dawn: 'bed', morning: 'sun', afternoon: 'utensils', night: 'moon'}
    }
  },
  computed: {
    todos() {
      return this.$store.state.todos
    }
  }
}
</script>

<style lang="scss" scoped>
#todolist {
  margin: 30px 30px;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
.item {
  background: white;
  width: 500px;
  margin: 5px;
  padding: 15px 20px;
  border-radius: 5px;
  display: flex;
  justify-content: center;
  flex-basis: fit-content;
  // https://getcssscan.com/css-box-shadow-examples
  box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px;

  .text {
    font-size: 20px;
    font-weight: 700;
    text-align: left;
    flex-grow: 1;
    flex-basis: fit-content;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: -3px;
  }
  .period {
    font-weight: 800;
    padding: 0.2em 0.4em;
    border-radius: 5px;
  }
  .dawn {
    background: grey;
    color: white;
  }
  .morning {
    background: orange;
    color: white;
  }
  .afternoon {
    background: skyblue;
    color: white;
  }
  .night {
    background: yellow;
  }
}
</style>

원래의 css 에서는 위처럼 계층형으로 작성할 수가 없다. 아래처럼, 스타일의 중첩 구조를 통해 css로 해석가능하게 바뀌게 된다.

<style>
  -- sass style
  .a {
    color: red;
    .b {
        color: blue;
    }
  }

  -- compiled to css like below

  .a {
    color: red;
  }
  .a .b {
    color: blue;
  }

</style>

css 를 이용해 간단하게 꾸며보자

내 생각에 css로 디자인하는 부분에서 제일 중요한건 레이아웃이다. 내가 이전에 고려했던대로 레이아웃만 잘 설계하면, 색을 입히거나 디테일을 챙기는 것은 오히려 어렵지 않을 거다.

그 레이아웃을 잡기 위해서는 css 의 flex를 이용하는 것이 제일 편리한 방법일 것이다.

먼저 레이아웃을 구상해보면

todolist 영역 안에 할일 목록을 수직으로 쌓아내려야 한다

위 구조대로 보여주기 위해서는 `display: flex;` 가 시작이다.

위 속성을 설정한 div 영역 (여기서는 Todolist) 은 flex container가 되어서 편리하게 레이아웃을 구상대로 구현할 수 있도록 설정될 것이다.

위 레이아웃을 위한 기본 css 적용

.container {
  display: flex; 
  justify-content: center;
  align-items: center;
  flex-direction: column;
}
.item {
  width: 500px;    
}

부모인 container에 적용할 속성들

  • display: flex;
    • flex container로 만들어준다
  • justify-content: center;
    • x 축 기준으로 내부 아이템들을 가운데로 정렬해준다
  • align-items: center;
    • y 축 기준으로 내부 아이템들을 가운데로 정렬해준다
  • flex-direction: column;
    • item들이 쌓여갈때 수직으로 쌓도록 한다

이에 더불어 위 레이아웃처럼 하려면, item과 그 하위 컨텐츠인 text, period도 부모컨테이너와 자식요소 관계로, 똑같이 flex를 적용해야 한다.
이경우엔 자식이 가로로 배치가 되므로 flex-direction 항목을 제외해주면 된다. 자세한 스타일내용은 위에 나타나있다.

css가 적용된 할일 목록의 모습

fortAwesome 을 도입해 예쁜 아이콘을 추가해보자

웹사이트를 이용하다보면 직관적이고 귀여운 emoji들을 통해 이게 뭔기능인지 그림으로 쉽게 이해할 수 있다.

단순히 텍스트로만 전달하기보단 그림들을 넣어서 더 세련되게 바꿀 수 있지 않을까?

  1. npm 으로 fortawesome을 설치
  2. npm i --save @fortawesome/fontawesome-svg-core npm i --save @fortawesome/free-solid-svg-icons
  3. fortawesome component를 vue app에 전역적으로 추가
    import {createApp} from 'vue'
    import App from './App.vue'
    import store from './store.js'
    
    //font-awesome
    import {library} from '@fortawesome/fontawesome-svg-core'
    import {faSun, faBed, faCalendarDay, faMoon, faUtensils} from '@fortawesome/free-solid-svg-icons'
    import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'
    library.add(faSun, faBed, faCalendarDay, faMoon, faUtensils)
    
    const app = createApp(App)
    app.component('font-awesome-icon', FontAwesomeIcon)
    
    app.use(store)
    app.mount('#app')​
  4. 쓰고자하는 컴포넌트에서 `FontAwersomeIcon` 을 kebab-case 변환해 html tag로 추가
<template>
  <div id="todolist">
    <div class="item" v-for="data in todos" :key="data.id">
      <div class="text">{{ data.content }}</div>
      <div :class="'period ' + data.period">
        {{ this.periods[data.period] }}
        <font-awesome-icon :icon="this.icons[data.period]" :color="this.colors[data.period]" />
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      periods: {dawn: '새벽', morning: '아침', afternoon: '낮', night: '저녁'},
      colors: {dawn: '#FFFFFF', morning: '#FFFFFF', afternoon: '#FFFFFF', night: '#000000'},
      icons: {dawn: 'bed', morning: 'sun', afternoon: 'utensils', night: 'moon'}
    }
  },
  computed: {
    todos() {
      return this.$store.state.todos
    }
  }
}
</script>
# 생략
<style lang="scss" scoped>

</style>

<font-awesome-icon :icon="this.icons[data.period]" :color="this.colors[data.period]" />
v-bind:attribute 를 통해, 쓰고자 하는 icon 의 이름과 그 색깔을 동적으로 바인딩해주었다.

google font를 추가하자

vue 기본폰트는 뭔가 맘에 들지 않아 google font 를 추가해 적용하기로 했다.
나의 경우엔 나눔고딕을 좋아해서 이걸 쓰기로 했다.

[https://fonts.google.com/specimen/Nanum+Gothic#glyphs](구글폰트 나눔고딕)

css 스타일을 선택후 우측 import문과 css rule을 복사해놓자

@import문을 style tag 맨 처음에, css rule을 해당 폰트를 디폴트로 적용할 영역에 추가한다.

<!-- App.vue -->
<template>
  <Title name="두루뭉실 투두" />
  <to-do-input />
  <to-do-list />
</template>

<script>
import Title from './components/Title.vue'
import ToDoInput from './components/ToDoInput.vue'
import ToDoList from './components/ToDoList.vue'

export default {
  name: 'App',
  components: {
    Title,
    ToDoInput,
    ToDoList
  }
}
</script>

// https://colorhunt.co/palette/161853292c6dfaedf0ec255a
<style>
@import url('https://fonts.googleapis.com/css2?family=Nanum+Gothic:wght@400;700;800&display=swap');
#app {
  font-family: 'Nanum Gothic', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
html,
body {
  background: #faedf0;
}
</style>

 

 

마무리

맨처음에 비하면 조금이나마 보기 좋게 바뀌었다

여러 간단한 과정을 종합해서 그나마 todo list라고 볼 수는 있을만큼 디자인을 했다.

나만의 뚜렷한 미적감각이 없기에 색조합은 아래의 사이트를 이용했다. 같이 쓰기 좋은 색조합을 보여주는 유틸리티 웹사이트다.

https://colorhunt.co/

 

Color Palettes for Designers and Artists - Color Hunt

Discover the newest hand-picked color palettes of Color Hunt. Get color inspiration for your design and art projects.

colorhunt.co

자세히 보면 container 내 할일 아이템들에 그림자가 있는걸 볼 수 있는데, 내가 특정 아이템에 그림자를 다른 방식으로 주고 싶다면

아래 웹에서 골라서 사용하면 편리할 것이다.

https://getcssscan.com/css-box-shadow-examples

 

CSS Scan - The fastest and easiest way to check, copy and edit CSS

Goodbye to "Inspect Element" — Visualize the CSS of any element you hover over, instantly, and copy its entire rules with a single click.

getcssscan.com