RootController
templates에 root / index.html
templates에 fragments / header.html
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<header class="header" th:fragment="content">
<div class="top-bar">
<ul class="list">
<li class="item">
<a class="link" href="#">즐겨찾기</a>
</li>
<li class="item">
<a class="link" href="#">입점신청</a>
</li>
<li class="spring"></li>
<li class="item">
<a class="link" th:href="@{/user/login}">로그인</a>
</li>
<li class="item">
<a class="link" th:href="@{/user/register}">회원가입</a>
</li>
<li class="item">
<a class="link" href="#">고객센터</a>
</li>
</ul>
</div>
<div class="search">
<a class="logo-container" th:href="@{/}">
<img alt="Coupang" class="logo" th:src="@{/resources/images/logo.png}">
</a>
<form th:action="@{/shopping/search}" class="search-form" method="get">
<label class="keyword-input-container">
<span hidden>검색어</span>
<input class="keyword-input" maxlength="50" name="keyword" placeholder="찾고 싶은 상품을 검색해보세요!" type="text">
</label>
<button class="search-button">
<i class="icon fa-solid fa-magnifying-glass"></i>
</button>
</form>
<ul class="my">
<li class="item">
<a class="link" th:href="@{user/my}">
<i class="icon fa-solid fa-user"></i>
<span class="text">마이쿠팡</span>
</a>
</li>
<li class="item">
<a class="link" th:href="@{/shopping/cart}">
<i class="icon fa-solid fa-cart-shopping"></i>
<span class="text">장바구니</span>
<span class="count">0</span>
</a>
</li>
</ul>
</div>
</header>
</html>
templates에 user / login.html
<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>로그인</title>
<link th:href="@{resources/stylesheets/common.css}" rel="stylesheet">
<link th:href="@{/user/resources/stylesheets/login.css}" rel="stylesheet">
<script src="https://kit.fontawesome.com/0d51ab0f86.js" crossorigin="anonymous"></script>
</head>
<body>
<form class="login-form" method="post">
<div class="logo-container">
<img alt="Coupang" class="logo" th:src="@{/resources/images/logo.png}">
</div>
<label class="input-container">
<i class="icon fa-solid fa-envelope"></i>
<span hidden>이메일</span>
<input autofocus class="input" maxlength="50" name="email" placeholder="아이디(이메일)" type="email">
</label>
<label class="input-container">
<i class="icon fa-solid fa-key"></i>
<span hidden>비밀번호</span>
<input class="input" maxlength="50" name="password" placeholder="비밀번호" type="password">
</label>
<div class="sub">
<label class="autosign-container">
<input class="checkbox" name="autosign" type="checkbox">
<span class="checker">
<i class="icon fa-solid fa-ch eck"></i>
</span>
<span class="text">자동로그인</span>
</label>
<a class="link" th:href="@{/user/recover}">아이디(이메일)/비밀번호 찾기</a>
</div>
<input class="button login" type="submit" value="로그인">
<div class="line"></div>
<a class="button register" th:href="@{/user/register}">회원가입</a>
<span class="copyright">©Coupang Corp. All rights reserved</span>
</form>
</body>
</html>
templates에 user / register.html
<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>회원가입</title>
<link th:href="@{resources/stylesheets/common.css}" rel="stylesheet">
<link th:href="@{/user/resources/stylesheets/register.css}" rel="stylesheet">
<script src="https://kit.fontawesome.com/0d51ab0f86.js" crossorigin="anonymous"></script>
</head>
<body>
<form class="register-form" method="post">
<div class="logo-container">
<img alt="Coupang" class="logo" th:src="@{/resources/images/logo.png}">
</div>
<div class="section-title">회원정보를 입력해주세요</div>
<label class="input-container">
<i class="icon fa-solid fa-envelope"></i>
<span hidden>이메일</span>
<input autofocus class="input" maxlength="50" name="email" placeholder="아이디(이메일)" type="email">
</label>
<label class="input-container">
<i class="icon fa-solid fa-key"></i>
<span hidden>비밀번호</span>
<input class="input" maxlength="50" name="password" placeholder="비밀번호" type="password">
</label>
<label class="input-container">
<i class="icon fa-solid fa-lock"></i>
<span hidden>비밀번호 확인</span>
<input class="input" maxlength="50" name="password" placeholder="비밀번호 확인" type="password">
</label>
<label class="input-container">
<i class="icon fa-solid fa-user"></i>
<span hidden>이름</span>
<input class="input" maxlength="50" name="name" placeholder="이름" type="text">
</label>
<label class="input-container">
<i class="icon fa-solid fa-phone"></i>
<span hidden>휴대폰 번호</span>
<input class="input" maxlength="10" name="tel" placeholder="휴대폰 번호" type="tel">
</label>
<div class="line"></div>
<input class="button register" type="submit" value="가입하기">
<span class="copyright">©Coupang Corp. All rights reserved</span>
</form>
</body>
</html>
resources 에 static 안에 resources / stylesheets / common.css
@charset "UTF-8";
@import "header.css";
:root {
--content-max-width: 75rem;
}
html {
font-family: 'Pretendard', sans-serif;
font-weight: 300;
}
a:link, a:visited {
color: unset;
text-decoration: unset;
}
body {
width: 100%;
min-height: 100%;
align-items: stretch;
display: flex;
flex-direction: column;
font-size: 0.9rem;
justify-content: flex-start;
margin: unset;
position: absolute;
}
input {
width: 100%;
appearance: none;
background-color: unset;
border: unset;
border-image: unset;
box-sizing: border-box;
color: unset;
font: unset;
margin: unset;
outline: unset;
padding: unset;
}
ol, ul {
list-style-type: none;
margin-block: unset;
margin-inline: unset;
padding-inline: unset;
}
resources 에 static 안에 resources / stylesheets / header.css
body > .header {
width: 100%;
align-items: center;
border-bottom: 0.0625rem solid rgb(229, 229, 229);
display: flex;
flex-direction: column;
justify-content: flex-start;
}
body > .header > .top-bar {
width: 100%;
align-items: center;
background-color: rgb(239, 239, 239);
display: flex;
flex-direction: column;
font-size: 0.75rem;
justify-content: flex-start;
padding: 0.5rem 0;
}
body > .header > .top-bar > .list {
width: var(--content-max-width);
align-items: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
body > .header > .top-bar > .list > .spring {
flex: 1;
}
body > .header > .top-bar > .list > .item + .item {
margin-left: 0.75rem;
}
body > .header > .search {
width: var(--content-max-width);
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 2rem 0;
}
body > .header > .search > .logo-container > .logo {
height: 2.5rem;
}
body > .header > .search > .search-form {
left: 50%;
align-items: center;
display: flex;
flex-direction: row;
justify-content: center;
position: absolute;
transform: translateX(-50%);
}
body > .header > .search > .search-form > .keyword-input-container > .keyword-input {
width: 30rem;
border: 0.125rem solid rgb(66, 132, 263);
font-size: 1rem;
padding: 0.7rem 3rem 0.7rem 1rem;
}
body > .header > .search > .search-form > .search-button {
top: 50%;
right: 1rem;
appearance: none;
background-color: unset;
border: none;
cursor: pointer;
margin: unset;
padding: unset;
position: absolute;
transform: translateY(-50%);
}
body > .header > .search > .search-form > .search-button > .icon {
color: rgb(66, 132, 246);
font-size: 1.125rem;
}
body > .header > .search > .my {
align-items: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
body > .header > .search > .my > .item + .item {
margin-left: 1.5rem;
}
body > .header > .search > .my > .item > .link {
align-items: center;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
}
body > .header > .search > .my > .item > .link > .icon {
color: rgb(85, 85, 85);
font-size: 1.5rem;
margin-bottom: 0.425rem;
}
body > .header > .search > .my > .item > .link > .count {
top: -0.625rem;
right: 0.125rem;
height: 1.25rem;
align-items: center;
background-color: rgb(66, 132, 243);
border-radius: 10rem;
color: rgb(255, 255, 255);
display: flex;
flex-direction: row;
font-size: 0.7rem;
font-weight: 600;
justify-content: center;
padding: 0 0.375rem;
position: absolute;
}
static 안에 user / stylesheets / login.css
@charset "UTF-8";
body {
background-color: rgb(254, 254, 254);
padding: 3rem;
}
body > .login-form {
align-items: center;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
body > .logo-container {
align-items: center;
display: flex;
flex-direction: row;
justify-content: center;
margin-bottom: 1.5rem;
}
body > .login-form > .logo-container > .logo {
height: 2.5rem;
}
body > .login-form > .input-container {
align-items: stretch;
border: 0.0625rem solid rgb(203, 203, 203);
display: flex;
flex-direction: row;
justify-content: flex-start;
margin-top: 0.75rem;
}
body > .login-form > .input-container:focus-within {
border-bottom: 0.0625rem solid rgb(66, 132, 243);
}
body > .login-form > .input-container > .icon {
width: 3rem;
height: 2.75rem;
align-items: center;
background-color: rgb(249, 249, 249);
border-right: 0.0625rem solid rgb(203, 203, 203);
color: rgb(203, 203, 203);
font-size: 1.125rem;
display: flex;
flex-direction: row;
justify-content: center;
}
body > .login-form > .input-container > .input {
width: 20rem;
padding: 0.8rem;
}
body > .login-form > .sub {
align-items: center;
align-content: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
margin: 13px 0 0;
font-size: 14px;
}
body > .login-form > .sub > .autosign-container {
align-items: center;
cursor: pointer;
display: flex;
flex-direction: row;
justify-content: flex-start;
user-select: none;
width: 15rem;
}
body > .login-form > .sub > .autosign-container > .checkbox {
display: none;
}
body > .login-form > .sub > .autosign-container > .checker {
width: 1.125rem;
height: 1.125rem;
border: 0.0625rem solid rgb(203, 203, 203);
position: relative;
}
body > .login-form > .sub > .autosign-container > .checker > .icon {
top: calc(50% + 0.25rem);
left: 50%;
color: rgb(66, 132, 243);
font-size: 0.8rem;
opacity: 0;
position: absolute;
transform: translate(-50%, -50%);
transition-duration: 250ms;
transition-property: top, opacity;
transition-timing-function: ease;
}
body > .login-form > .sub > .autosign-container > checkbox:checked + .checker > .icon {
top: 50%;
opacity: 1;
}
body > .login-form > .sub > .autosign-container > .text {
top: -0.125rem;
margin-left: 0.5rem;
position: relative;
white-space: nowrap;
}
body > .login-form > .sub > .link {
color: rgb(66, 132, 243);
text-decoration: none;
}
body > .login-form > .button {
width: 25.5rem;
border-radius: 0.25rem;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
margin-top: 0.75rem;
padding: 0.75rem 0;
text-align: center;
user-select: none;
color: #0073e9;
text-decoration: none;
border: 1px solid #ccc;
}
body > .login-form > .button-login {
background-color: rgb(66, 132, 243);
color: rgb(255, 255, 255);
}
body > .login-form > .button.login:hover {
filter: brightness(110%);
}
body > .login-form > .button.login:active {
filter: brightness(90%);
}
body > .login-form > .button.login {
border-top: 0.0625rem solid rgb(209, 209, 209);
font-weight: 700;
text-decoration: none;
font-size: 17px;
background-color: #0074e9;
color: white;
}
body > .login-form > .line {
border-top: 0.0625rem solid rgb(209, 209, 209);
margin-top: 0.75rem;
display: block;
width: 34%;
height: 0;
padding: 0;
}
body > .login-form > .copyright {
font-size: 0.8rem;
margin-top: 1.5rem;
text-align: center;
}
static 안에 user / stylesheets / register.css
@charset "UTF-8";
body {
background-color: rgb(254, 254, 254);
padding: 3rem;
}
body > .register-form {
align-items: center;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
body > .logo-container {
align-items: center;
display: flex;
flex-direction: row;
justify-content: center;
margin-bottom: 1.5rem;
}
.section-title {
padding: 30px 0px 10px 0;
font-size: 15px;
font-weight: bold;
line-height: 0.0625rem;
color: #111;
margin-right: 15rem;
}
body > .register-form > .logo-container > .logo {
height: 2.5rem;
}
body > .register-form > .input-container {
align-items: stretch;
border: 0.0625rem solid rgb(203, 203, 203);
display: flex;
flex-direction: row;
justify-content: flex-start;
margin-top: 0.75rem;
}
body > .register-form > .input-container:focus-within {
border-bottom: 0.0625rem solid rgb(66, 132, 243);
}
body > .register-form > .input-container > .icon {
width: 3rem;
height: 2.75rem;
align-items: center;
background-color: rgb(249, 249, 249);
border-right: 0.0625rem solid rgb(203, 203, 203);
color: rgb(203, 203, 203);
font-size: 1.125rem;
display: flex;
flex-direction: row;
justify-content: center;
}
body > .register-form > .input-container > .input {
width: 20rem;
padding: 0.8rem;
}
body > .register-form > .sub {
align-items: center;
display: flex;
flex-direction: row;
justify-content: space-between;
}
body > .register-form > .sub > .autosign-container {
align-items: center;
cursor: pointer;
display: flex;
flex-direction: row;
justify-content: flex-start;
user-select: none;
width: 15rem;
}
body > .register-form > .sub > .autosign-container > .checkbox {
display: none;
}
body > .register-form > .sub > .autosign-container > .checker {
width: 1.125rem;
height: 1.125rem;
border: 0.0625rem solid rgb(203, 203, 203);
position: relative;
}
body > .register-form > .sub > .autosign-container > .checker > .icon {
top: calc(50% + 0.25rem);
left: 50%;
color: rgb(66, 132, 243);
font-size: 0.8rem;
opacity: 0;
position: absolute;
transform: translate(-50%, -50%);
transition-duration: 250ms;
transition-property: top, opacity;
transition-timing-function: ease;
}
body > .register-form > .sub > .autosign-container > checkbox:checked + .checker > .icon {
top: 50%;
opacity: 1;
}
body > .register-form > .sub > .autosign-container > .text {
top: -0.125rem;
margin-left: 0.5rem;
position: relative;
white-space: nowrap;
}
body > .register-form > .sub > .link {
color: rgb(66, 132, 243);
}
body > .register-form > .button {
width: 25.5rem;
border-radius: 0.25rem;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
margin-top: 0.75rem;
padding: 0.75rem 0;
text-align: center;
user-select: none;
}
body > .register-form > .button-register {
background-color: rgb(66, 132, 243);
color: rgb(255, 255, 255);
}
body > .register-form > .button.register:hover {
filter: brightness(110%);
}
body > .register-form > .button.register:active {
filter: brightness(90%);
}
body > .register-form > .button.register {
border: 0.0625rem solid rgb(209, 209, 209);
padding: 1rem 3rem;
font-weight: 700;
text-decoration: none;
font-size: 17px;
background-color: #0074e9;
color: white;
}
body > .register-form > .line {
border-top: 0.0625rem solid rgb(209, 209, 209);
margin-top: 0.75rem;
display: block;
width: 34%;
height: 0;
padding: 0;
}
body > .register-form > .copyright {
font-size: 0.7rem;
margin-top: 1.5rem;
text-align: center;
}