[React] Movie app clone coding : Giving some CSS to

5 minute read

7-2. Giving some CSS to

  • To install it run:

    1yarn add react-lines-ellipsis
    

CSS 꾸미기

App.css

 1.App {
 2    padding: 50px;
 3    display: flex;
 4    justify-content: space-around;
 5    flex-wrap: wrap;
 6    font-size: 14px;
 7}
 8
 9.App--loading{
10    display: flex;
11    justify-content: center;
12    align-items: center;
13    height: 100%;
14}

App.js

1  render() {
2    const {movie} = this.state;
3    return (
4      <div className={movie ? "App" : "App--loading"}>
5        {movies ? this._renderMovies() : 'Loading'}
6      </div>
7    );
8  }
9}
  • <div className={movie ? "App" : "App--loading"}>

    movies가 있으면 div의 이름은 app이 되고, movies가 없으면 app-loading이 된다.

  • 그리고 각각의 css를 App.css 에 정했다.

index.css

 1body {
 2  margin: 0;
 3  padding: 0;
 4  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
 5  background-color:#EFF3F7;
 6  height: 100%;
 7}
 8
 9html, #root{
10  height:100%;
11}

Movie.css

 1.Movie{
 2    background-color:white;
 3    width:40%;
 4    display: flex;
 5    justify-content: space-between;
 6    align-items:flex-start;
 7    flex-wrap:wrap;
 8    margin-bottom:50px;
 9    text-overflow: ellipsis;
10    padding:0 20px;
11    box-shadow: 0 8px 38px rgba(133, 133, 133, 0.3), 0 5px 12px rgba(133, 133, 133,0.22);
12}
13
14.Movie__Column{
15    width:30%;
16    box-sizing:border-box;
17    text-overflow: ellipsis;
18}
19
20.Movie__Column:last-child{
21    padding:20px 0;
22    width:60%;
23}
24
25.Movie h1{
26    font-size:20px;
27    font-weight: 600;
28}
29
30.Movie .Movie__Genres{
31    display: flex;
32    flex-wrap:wrap;
33    margin-bottom:20px;
34}
35
36.Movie__Genres .Movie__Genre{
37    margin-right:10px;
38    color:#B4B5BD;
39}
40
41.Movie .Movie__Synopsis {
42    text-overflow: ellipsis;
43    color:#B4B5BD;
44    overflow: hidden;
45}
46
47.Movie .Movie__Poster{
48    max-width: 100%;
49    position: relative;
50    top:-20px;
51    box-shadow: -10px 19px 38px rgba(83, 83, 83, 0.3), 10px 15px 12px rgba(80,80,80,0.22);
52}
53
54/* Mobile Phone */
55@media screen and (min-width:320px) and (max-width:667px){
56    .Movie{
57        width:100%;
58    }
59}
60
61/* Mobile-portrait */
62@media screen and (min-width:320px) and (max-width:667px) and (orientation: portrait){
63    .Movie{
64        width:100%;
65        flex-direction: column;
66    }
67    .Movie__Poster{
68        top:0;
69        left:0;
70        width:100%;
71    }
72    .Movie__Column{
73        width:100%!important;
74    }
75}

Movie.js

 1import LinesEllipsis from 'react-lines-ellipsis'
 2import './Movie.css';
 3
 4function Movie({title, poster, genres, synopsis}){
 5  return(
 6       ...
 7        <p className="Movie__Synopsis">
 8         
 9      /* Synopsis를 줄여주는 역할 : 
10       * npm install --save react-lines-ellipsis 
11       */
12          <LinesEllipsis      
13            text={synopsis}
14            maxLine='3'
15            ellipsis='...'
16            trimRight
17            basedOn='letters'
18          />   
19        </p>
20      ...
21  )
22}

전체코드

App.js

 1import React, { Component } from 'react';
 2import './App.css';
 3import Movie from './Movie';
 4
 5class App extends Component {
 6
 7  state = {}
 8
 9  componentDidMount(){
10    this._getMovies();    // 큰 사이즈의 componentDidMount를 갖고 싶지 않으므로
11  }
12
13  _renderMovies = () => {
14    const movies = this.state.movies.map((movie, index) => {
15      return <Movie 
16        title={movie.title_english} 
17        poster={movie.medium_cover_image} 
18        key={movie.id} 
19        genres={movie.genres}
20        synopsis={movie.synopsis} 
21      />
22    })
23    return movies
24  }
25
26  _getMovies = async() => {
27    const movies = await this._callApi()
28    this.setState({
29      movies
30    })
31  }
32
33
34  _callApi = () => {
35    return fetch('https://yts.am/api/v2/list_movies.json?sort_by=rating')
36    .then(response => response.json())
37    .then(json => json.data.movies)
38    .catch(err => console.log('error'))
39  }
40
41
42  render() {
43    const {movies} = this.state;
44    return (
45      <div className={movies ? "App" : "App--loading"}>
46        {movies ? this._renderMovies() : 'Loading'}
47      </div>
48    );
49  }
50}
51
52export default App;

App.css

 1.App {
 2    padding: 50px;
 3    display: flex;
 4    justify-content: space-around;
 5    flex-wrap: wrap;
 6    font-size: 14px;
 7}
 8
 9.App--loading{
10    display: flex;
11    justify-content: center;
12    align-items: center;
13    height: 100%;
14}

Movie.js

 1import React from 'react';
 2import propTypes from 'prop-types';
 3import LinesEllipsis from 'react-lines-ellipsis'
 4import './Movie.css';
 5
 6function Movie({title, poster, genres, synopsis}){
 7  return(
 8    <div className="Movie">
 9      <div className="Movie__Columns">
10        <MoviePoster poster={poster} alt={title} />  
11      </div>
12      <div className="Movie__Columns">
13        <h1>{title}</h1>
14        <div className="Movie__Genres">
15          {genres.map((genre, index) => <MovieGenre genre={genre} key={index} />)}
16        </div>
17        <p className="Movie__Synopsis">
18          <LinesEllipsis      
19            text={synopsis}
20            maxLine='3'
21            ellipsis='...'
22            trimRight
23            basedOn='letters'
24          />   
25        </p>
26
27      </div>
28    </div>
29  )
30}
31
32function MoviePoster({poster, alt}) {
33  return(
34    <img src={poster} alt={alt} title={alt} className="Movie__Poster" />
35  )
36}
37
38
39function MovieGenre({genre}){
40  return(
41    <span className="Movie__Genre">{genre}</span>
42  )
43}
44
45
46Movie.propTypes = {
47  title: propTypes.string.isRequired,
48  poster: propTypes.string.isRequired,
49  genres: propTypes.array.isRequired,
50  synopsis: propTypes.string.isRequired
51}
52
53MoviePoster.propTypes = {
54  poster: propTypes.string.isRequired,
55  alt: propTypes.string.isRequired
56}
57
58MovieGenre.prototype ={
59  genre: propTypes.string.isRequired
60}
61
62
63export default Movie;

Movie.css

 1.Movie{
 2    background-color:white;
 3    width:40%;
 4    display: flex;
 5    justify-content: space-between;
 6    align-items:flex-start;
 7    flex-wrap:wrap;
 8    margin-bottom:50px;
 9    text-overflow: ellipsis;
10    padding:0 20px;
11    box-shadow: 0 8px 38px rgba(133, 133, 133, 0.3), 0 5px 12px rgba(133, 133, 133,0.22);
12}
13
14.Movie__Column{
15    width:30%;
16    box-sizing:border-box;
17    text-overflow: ellipsis;
18}
19
20.Movie__Column:last-child{
21    padding:20px 0;
22    width:60%;
23}
24
25.Movie h1{
26    font-size:20px;
27    font-weight: 600;
28}
29
30.Movie .Movie__Genres{
31    display: flex;
32    flex-wrap:wrap;
33    margin-bottom:20px;
34}
35
36.Movie__Genres .Movie__Genre{
37    margin-right:10px;
38    color:#B4B5BD;
39}
40
41.Movie .Movie__Synopsis {
42    text-overflow: ellipsis;
43    color:#B4B5BD;
44    overflow: hidden;
45}
46
47.Movie .Movie__Poster{
48    max-width: 100%;
49    position: relative;
50    top:-20px;
51    box-shadow: -10px 19px 38px rgba(83, 83, 83, 0.3), 10px 15px 12px rgba(80,80,80,0.22);
52}
53
54/* Mobile Phone */
55@media screen and (min-width:320px) and (max-width:667px){
56    .Movie{
57        width:100%;
58    }
59}
60
61/* Mobile-portrait */
62@media screen and (min-width:320px) and (max-width:667px) and (orientation: portrait){
63    .Movie{
64        width:100%;
65        flex-direction: column;
66    }
67    .Movie__Poster{
68        top:0;
69        left:0;
70        width:100%;
71    }
72    .Movie__Column{
73        width:100%!important;
74    }
75}

index.css

 1body {
 2  margin: 0;
 3  padding: 0;
 4  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
 5  background-color:#EFF3F7;
 6  height: 100%;
 7}
 8
 9html, #root{
10  height:100%;
11}