https://github.com/d36choi/extodo/tree/feat/css
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
를 이용하는 것이 제일 편리한 방법일 것이다.
먼저 레이아웃을 구상해보면
위 구조대로 보여주기 위해서는 `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 항목을 제외해주면 된다. 자세한 스타일내용은 위에 나타나있다.
fortAwesome 을 도입해 예쁜 아이콘을 추가해보자
웹사이트를 이용하다보면 직관적이고 귀여운 emoji들을 통해 이게 뭔기능인지 그림으로 쉽게 이해할 수 있다.
단순히 텍스트로만 전달하기보단 그림들을 넣어서 더 세련되게 바꿀 수 있지 않을까?
- npm 으로 fortawesome을 설치
npm i --save @fortawesome/fontawesome-svg-core npm i --save @fortawesome/free-solid-svg-icons
- 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')
- 쓰고자하는 컴포넌트에서 `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](구글폰트 나눔고딕)
@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라고 볼 수는 있을만큼 디자인을 했다.
나만의 뚜렷한 미적감각이 없기에 색조합은 아래의 사이트를 이용했다. 같이 쓰기 좋은 색조합을 보여주는 유틸리티 웹사이트다.
자세히 보면 container 내 할일 아이템들에 그림자가 있는걸 볼 수 있는데, 내가 특정 아이템에 그림자를 다른 방식으로 주고 싶다면
아래 웹에서 골라서 사용하면 편리할 것이다.
https://getcssscan.com/css-box-shadow-examples