whatisthis?

practice - css ) BookStore UI 본문

PRACTICE/SELF

practice - css ) BookStore UI

thisisyjin 2022. 3. 12. 16:16

 BookStore UI

-codepen

 

 

HTML / CSS practice

 

🏆 KEY POINTS

  • display: flex와 flex-shrink
  • position: absolute

 

  • FontAwesome 사용 - 다른 방법!
@import url(//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css);

.rating > label::before {
  display: inline-block;
  font-size: 0.9em;
  font-family: FontAwesome;
  content: "\f005";
}

 

  • transition과 가상클래스

 

  • overflow

overflow와 text-overflow의 차이는?

 

  • text-overflow: ellipsis

텍스트가 넘치면 ellipsis (...) 로 중략되게 자동으로!

 

  • white-space: nowrap

내용이 넘쳐도 줄바꿈 절대 X.

 

  • display: --webkit-box

 

  • ❗❗ rating - 별점 부분 CSS

 

<fieldset class="rating purple">
  <input type="checkbox" id="star1" name="rating" value="5" />
  <label class="full" for="star1"></label>
  <input type="checkbox" id="star2" name="rating" value="4" />
  <label class="full" for="star2"></label>
  <input type="checkbox" id="star3" name="rating" value="3" />
  <label class="full" for="star3"></label>
  <input type="checkbox" id="star4" name="rating" value="2" />
  <label class="full" for="star4"></label>
  <input type="checkbox" id="star5" name="rating" value="1" />
  <label class="full" for="star5"></label>
</fieldset>

우선, fieldset 안에 묶어두고,

checkbox와 label 쌍을 sibling이 되도록 마크업함.

순서대로 별5, 4, 3, 2, 1 임.

 

 

.rating > label {
  float: right;
}

float: right해서 원래 5-4-3-2-1 이렇게 있던 거를

star1 star2 star3 star4 star5

 

이렇게 바꿔줌. float하므로 오른쪽으로 먼저 채운거임.

 

.rating > input:checked ~ label,
.rating:not(:checked) > label:hover,
.rating:not(:checked) > label:hover ~ label {
  color: #d85d61;
}

그리고 input이 check되면 - :checked 라는 가상클래스 이용.

~label은 ? >> checked된것 이후 label들 다~ (sibling selector)

 

 

💡

즉, 마크업 순서가 5-4-3-2-1이였던 이유가 

css 상 float:right되어있어 1-2-3-4-5이고, 5를 체크시

html구조상으론 5이후 라벨들 다~ (5,4,3,2,1 전부) 적용되도록 하는것임!

 

 

그리고, :not이라는 가상클래스도 나오는데, checked가 아닌 나머지 .rating,즉 인풋의 자식 라벨들에 hover시

라벨과 그 이후 라벨들에도 스타일을 적용해줌.

 

 

 

 

 

 

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Book Store</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <header class="header">
      <div class="browse">
        <div class="browse-category">
          Browse Category
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
            class="feather feather-chevron-down"
          >
            <path d="M6 9l6 6 6-6" />
          </svg>
        </div>
        <div class="search-bar">
          <input type="text" placeholder="Search Book" />
        </div>
      </div>
      <div class="header-title">read<span>books</span></div>
      <div class="profile">
        <div class="user-profile">
          <img
            src="https://randomuser.me/api/portraits/women/63.jpg"
            alt="user123"
            class="user-img"
          />
        </div>
        <div class="profile-menu">
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            stroke-width="2"
            stroke-linecap="round"
            stroke-linejoin="round"
            class="feather feather-menu"
          >
            <path d="M3 12h18M3 6h18M3 18h18" />
          </svg>
          Menu
        </div>
      </div>
    </header>

    <!-- book slide -->

    <div class="book-slide">
      <div
        class="book js-flickity"
        data-flickity-options='{ "wrapAround": true }'
      >
        <div class="book-cell">
          <div class="book-img">
            <img
              src="https://images-na.ssl-images-amazon.com/images/I/81WcnNQ-TBL.jpg"
              alt=""
              class="book-photo"
            />
          </div>
          <div class="book-content">
            <div class="book-title">BIG MAGIC</div>
            <div class="book-author">by Elizabeth Gilbert</div>
            <div class="rate">
              <fieldset class="rating">
                <input type="checkbox" name="rating" id="star5" value="5" />
                <label class="full" for="star5"></label>
                <input type="checkbox" name="rating" id="star4" value="4" />
                <label class="full" for="star4"></label>
                <input type="checkbox" name="rating" id="star3" value="3" />
                <label class="full" for="star3"></label>
                <input type="checkbox" name="rating" id="star2" value="2" />
                <label class="full" for="star2"></label>
                <input type="checkbox" name="rating" id="star1" value="1" />
                <label class="full" for="star1"></label>
              </fieldset>
              <span class="book-voters">1.987 voters</span>
            </div>
            <div class="book-sum">
              Readers of all ages and walks of life have drawn inspiration and
              empowerment from Elizabeth Gilbert’s books for years.
            </div>
            <div class="book-see">See The Book</div>
          </div>
        </div>
        <div class="book-cell">
          <div class="book-img">
            <img
              src="https://i.pinimg.com/originals/a8/b9/ff/a8b9ff74ed0f3efd97e09a7a0447f892.jpg"
              alt=""
              class="book-photo"
            />
          </div>
          <div class="book-content">
            <div class="book-title">Ten Thousand Skies Above You</div>
            <div class="book-author">by Claudia Gray</div>
            <div class="rate">
              <fieldset class="rating blue">
                <input type="checkbox" id="star6" name="rating" value="5" />
                <label class="full1" for="star6"></label>
                <input type="checkbox" id="star7" name="rating" value="4" />
                <label class="full1" for="star7"></label>
                <input type="checkbox" id="star8" name="rating" value="3" />
                <label class="full1" for="star8"></label>
                <input type="checkbox" id="star9" name="rating" value="2" />
                <label class="full1" for="star9"></label>
                <input type="checkbox" id="star10" name="rating" value="1" />
                <label class="full1" for="star10"></label>
              </fieldset>
              <span class="book-voters">1.987 voters</span>
            </div>
            <div class="book-sum">
              The hunt for each splinter of Paul's soul sends Marguerite racing
              through a war-torn San Francisco.
            </div>
            <div class="book-see book-blue">See The Book</div>
          </div>
        </div>

        <div class="book-cell">
          <div class="book-img">
            <img
              src="https://images-na.ssl-images-amazon.com/images/I/81af+MCATTL.jpg"
              alt=""
              class="book-photo"
            />
          </div>
          <div class="book-content">
            <div class="book-title">The Great Gatsby</div>
            <div class="book-author">by F.Scott Fitzgerald</div>
            <div class="rate">
              <fieldset class="rating yellow">
                <input type="checkbox" id="star16" name="rating" value="5" />
                <label class="full" for="star16"></label>
                <input type="checkbox" id="star17" name="rating" value="4" />
                <label class="full" for="star17"></label>
                <input type="checkbox" id="star18" name="rating" value="3" />
                <label class="full" for="star18"></label>
                <input type="checkbox" id="star19" name="rating" value="2" />
                <label class="full" for="star19"></label>
                <input type="checkbox" id="star20" name="rating" value="1" />
                <label class="full" for="star20"></label>
              </fieldset>
              <span class="book-voters">1.987 voters</span>
            </div>
            <div class="book-sum">
              The Great Gatsby, F. Scott Fitzgerald’s third book, stands as the
              supreme achievement of his career.
            </div>
            <div class="book-see book-yellow">See The Book</div>
          </div>
        </div>
        <div class="book-cell">
          <div class="book-img">
            <img
              src="https://images-na.ssl-images-amazon.com/images/I/81UWB7oUZ0L.jpg"
              alt=""
              class="book-photo"
            />
          </div>
          <div class="book-content">
            <div class="book-title">After You</div>
            <div class="book-author">by Jojo Moyes</div>
            <div class="rate">
              <fieldset class="rating purple">
                <input type="checkbox" id="star21" name="rating" value="5" />
                <label class="full" for="star21"></label>
                <input type="checkbox" id="star22" name="rating" value="4" />
                <label class="full" for="star22"></label>
                <input type="checkbox" id="star23" name="rating" value="3" />
                <label class="full" for="star23"></label>
                <input type="checkbox" id="star24" name="rating" value="2" />
                <label class="full" for="star24"></label>
                <input type="checkbox" id="star25" name="rating" value="1" />
                <label class="full" for="star25"></label>
              </fieldset>
              <span class="book-voters">1.987 voters</span>
            </div>
            <div class="book-sum">
              Louisa Clark is no longer just an ordinary girl living an ordinary
              life. After the transformative six months spent.
            </div>
            <div class="book-see book-purple">See The Book</div>
          </div>
        </div>
      </div>
      <div class="btn-grp">
        <button class="prev">&lt;</button>
        <button class="next">&gt;</button>
      </div>
    </div>
    <script src="app.js"></script>
  </body>
</html>

 

 

style.css

@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap");
@import url(//netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css);

:root {
  --body-color-light: #8b939c;
  --body-color: #3d4954;
  --border-color: #b8bec3;
  --placeholder: #ccd0d2;
}

* {
  box-sizing: 0;
  margin: 0;
}

body {
  font-family: "Roboto", sans-serif;
  font-weight: 400;
  color: var(--body-color);
  width: 100%;
  height: 100vh;
}

/* Reset CSS */

ul,
ol,
li {
  list-style: none;
  padding: 0;
}

a {
  text-decoration: none;
  color: inherit;
}

button {
  border: none;
}

input,
button,
textarea {
  font-family: "Roboto", sans-serif;
}

input:focus,
button:focus,
textarea:focus,
input:active,
button:active,
textarea:active {
  outline: none;
  box-shadow: none;
}

fieldset,
label {
  margin: 0;
  padding: 0;
  display: inline-block;
  vertical-align: middle;
}

/* Header page */

.header {
  display: flex;
  justify-content: space-between;
  padding: 0 30px;
  width: 100%;
  height: 70px;
  font-size: 14px;
  font-weight: 500;
  color: var(--body-color-light);
}

/* header - browse */
.header .browse {
  display: flex;
  align-items: center;
}

.header .browse .browse-category {
  display: flex;
  border-right: 1px solid var(--border-color);
  white-space: nowrap;
}

.header .browse svg {
  width: 16px;
  margin: 2px 10px 0 8px;
}

.header .search-bar {
  position: relative;
}

.header .search-bar input {
  display: block;
  width: 100%;
  height: 100%;
  border: none;
  padding: 0 10px 0 40px;
  color: var(--body-color);
  font-weight: 600;
  background-color: transparent;
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' stroke='%238b939c' stroke-width='3' stroke-linecap='round' stroke-linejoin='round' class='feather feather-search'%3e%3ccircle cx='11' cy='11' r='8'/%3e%3cpath d='M21 21l-4.35-4.35'/%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-size: 15px;
  background-position: 15px 50%;
}

.header .search-bar input::placeholder {
  color: var(--placeholder);
}

/* header - title  */

.header .header-title {
  font-size: 16px;
  font-weight: 400;
  margin: auto 120px auto 0;
}

.header .header-title span {
  font-weight: 700;
  color: var(--body-color);
}

/* header - profile*/

.header .profile {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.header .user-profile {
  position: relative;
  cursor: pointer;
  flex-shrink: 0;
}

.header .user-profile::before {
  content: "";
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background-color: #f86d72;
  border: 2px solid #fff;
  right: 12px;
  top: -2px;
}

.header .profile .user-img {
  display: block;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  margin-right: 15px;
}

.header .profile-menu {
  display: flex;
  border-left: 1px solid var(--border-color);
}

.header .profile-menu svg {
  width: 16px;
  margin: 0 8px 0 15px;
  flex-shrink: 0;
}

/* Book Slide Page */

.book-slide {
  width: 100%;
  position: relative;
}

.book {
  background-color: #fff;
  display: flex;
  width: calc(40% * 4);
  margin-left: -10%;
}

.js-flickity {
  transition: all 0.3s ease-out;
}

.book-cell {
  position: relative;
  display: flex;
  padding: 25px;
  width: 40%;
  height: 200px;
  margin-right: 1px;
}

.book-cell:nth-child(1) {
  background-color: #fbadaf;
}
.book-cell:nth-child(2) {
  background-color: #a4e0eb;
}
.book-cell:nth-child(3) {
  background-color: #fdca95;
}
.book-cell:nth-child(4) {
  background-color: #cbb5e2;
}

/* .flickity-page-dots {
  display: none;
}

.flickity-prev-next-button .arrow {
  fill: #d6d6d6;
}

.flickity-prev-next-button svg {
  left: 25%;
  top: 25%;
  width: 50%;
  height: 50%;
}

.flickity-prev-next-button.previous {
  left: 15px;
}
.flickity-prev-next-button.next {
  right: 15px;
}

.flickity-viewport {
  overflow: visible;
} */

.book-photo {
  width: 180px;
  flex-shrink: 0;
  bottom: -35px;
  border-radius: 2px;
  box-shadow: -2px 6px 19px 0px #7f818e;
  transition: all 0.3s ease;
}

.book-photo:hover {
  transform: scale(1.03);
}

.book-img {
  flex-shrink: 0;
}

.book-title {
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}

.book-author {
  margin-top: 3px;
  font-size: 14px;
  text-overflow: ellipsis;
  white-space: nowrap;
  overflow: hidden;
}

.book-content {
  padding: 0 20px;
  color: #fff;
  overflow: hidden;
}

.rating {
  border: none;
}

.rating > input {
  display: none;
}

.rating > label::before {
  margin-right: 5px;
  margin-top: 10px;
  font-size: 0.9em;
  font-family: FontAwesome;
  display: inline-block;
  content: "\f005";
}

.rating > label {
  color: #fff;
  float: right;
}

.rating > input:checked ~ label,
.rating:not(:checked) > label:hover,
.rating:not(:checked) > label:hover ~ label {
  color: #d85d61;
}

.blue > input:checked ~ label,
.blue:not(:checked) > label:hover,
.blue:not(:checked) > label:hover ~ label {
  color: #458997;
}

.purple > input:checked ~ label,
.purple:not(:checked) > label:hover,
.purple:not(:checked) > label:hover ~ label {
  color: #a76287;
}

.yellow > input:checked ~ label,
.yellow:not(:checked) > label:hover,
.yellow:not(:checked) > label:hover ~ label {
  color: #ffad58;
}

/*
굳이 이건 왜하는지 모르겠음 🔻
*/

/* 

.rating > input:checked + label:hover,
.rating > input:checked ~ label:hover,
.rating > label:hover ~ input:checked ~ label,
.rating > input:checked ~ label:hover ~ label {
  color: #d85d61;
}

.blue > input:checked + label:hover,
.blue > input:checked ~ label:hover,
.blue > label:hover ~ input:checked ~ label,
.blue > input:checked ~ label:hover ~ label {
  color: #458997;
}

.purple > input:checked + label:hover,
.purple > input:checked ~ label:hover,
.purple > label:hover ~ input:checked ~ label,
.purple > input:checked ~ label:hover ~ label {
  color: #a76287;
}

.yellow > input:checked + label:hover,
.yellow > input:checked ~ label:hover,
.yellow > label:hover ~ input:checked ~ label,
.yellow > input:checked ~ label:hover ~ label {
  color: #ffad58;
}

*/

.book-voters {
  color: #fff;
  vertical-align: sub;
  font-size: 13px;
  margin-left: 7px;
  white-space: nowrap;
}

.book-sum {
  margin-top: 20px;
  font-size: 14px;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-width: 300px;
}

.book-see {
  width: 160px;
  padding: 8px;
  margin-top: 25px;
  border-radius: 20px;
  background-color: #fff;
  color: #fbadaf;
  font-size: 14px;
  font-weight: 600;
  text-align: center;
}

.book-see:hover {
  color: #ff6e72;
}

.book-see.book-blue {
  color: #a4e0eb;
}

.book-see.book-blue:hover {
  color: #22cdec;
}
.book-see.book-yellow {
  color: #fdca95;
}

.book-see.book-yellow:hover {
  color: #fb9124;
}
.book-see.book-purple {
  color: #cbb5e2;
}

.book-see.book-purple:hover {
  color: #a764ec;
}

/*  buttons  */

.btn-grp button {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 50px;
  height: 50px;
  z-index: 1;
  background-color: rgba(0, 0, 0, 0.2);
  border-radius: 50%;
  font-size: 35px;
  color: #fff;
  transition: all 0.2s ease;
}

.btn-grp .prev {
  left: 10px;
}

.btn-grp .next {
  right: 10px;
}

.btn-grp button:hover {
  background-color: rgba(0, 0, 0, 0.4);
}

 

 

원래는 슬라이드 기능 구현을 js로 하는데,

무려 3000줄이라서 (...) 내가 간단히 다시 작성중이다.

 

추후 수정해서 업로드함.

 

 

 


 

 

result

 

 

 

 

 


 

 

 

실습하면서 메모한거 🔻

더보기

 text-overflow: ellipsis;
 white-space: nowrap;

white-space: nowrap 이거는 줄바꿈 안되게.
text-overflow는 
텍스트가 넘치면
ellipsis (...) 로 중략되게


__


.rating > label::before {
  font-size: 0.9em;
  font-family: FontAwesome;
  display: inline-block;
  content: "\f005";
}

폰트어썸 적용법
물론 import는 해야댐

 

svg는 색상변경도 되니까 참 편하다

얘도 그렇다.

텍스트처럼 취급하면된다.


__


.rating > label {
  color: #fff;
  float: right;
}

.rating > input:checked ~ label,
.rating:not(:checked) > label:hover,
.rating:not(:checked) > label:hover ~ label {
  color: #d85d61;
}

이부분 개쩐다!
별 레이팅!

sibling selctor를 잘 쓰자.

 

html에선 5-4-3-2-1이고

float: right로 1-2-3-4-5로 시각적으로 보이게 한 후에

5클릭하면?

~ 선택자에 의해 5이후 label들 (5,4,3,2,1)이 다 색 적용되는것.


__


display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;

webkit box라는건데
3줄로 제한하는거
+) 얘도 ...로 중략되는듯??

 

 

 

Reference &

Thanks to @Aysenur Turk!

 

Aysenur Turk on CodePen

UI Developer

codepen.io

 

 

사담 & 후기 👻

 

 

codepen 탐험하다가 발견했는데,
js가 너무 크고 구식버전 이길래 우선 버리고 (...제이쿼리 너무 싫ㄷ ㅏ..)
넘 맘에들었던 슬라이드식 UI만 클론 해봤다.

별거아닌데 왜이렇게 오래걸린건지 .. 하하
암튼 이제 리액트 공부하러 갈 시간!

이번주는 바쁘게 CSS 클론해보고 컴포넌트별 간단한거 구현을 해봤다.
아직 배우고싶은건 많지만 ...

나중에 또 css 공부하러 올때쯤이면 아마
리액트와 노드에 익숙해져서
scss로 작성하러 올 것 같다 !