-> header.html
<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>
-> 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;
}
-> login.html
<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" placeholder="아이디(이메일)" type="email">
</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>
<div class="sub">
<label class="autosign-container">
<input class="checkbox" name="autosign" type="checkbox">
<span class="checker">
<i class="icon fa-solid fa-check"></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>
-> login.css
@charset "UTF-8";
body {
background-color: rgb(254,254,254);
}
body > .login-form {
align-items: stretch;
display: flex;
flex-direction: column;
justify-content: center;
margin-top: 3rem;
}
body > .login-form > .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-bottom: 1rem;
}
body > .login-form > .input-container > .input {
margin-left: 0.8rem;
font-weight: 400;
}
body > .login-form > .input-container:focus-within {
border: 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: 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 > .sub {
align-items: center;
align-content: center;
display: flex;
flex-direction: row;
justify-content: space-between;
}
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;
font-weight: 400;
}
body > .login-form > .sub > .link {
color: rgb(66, 132, 243);
text-decoration: none;
font-weight: 500;
}
body > .login-form > .button {
border-radius: 0.25rem;
cursor: pointer;
font-size: 1rem;
font-weight: 600;
margin-top: 1rem;
padding: 0.75rem 0;
user-select: none;
}
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.register {
border: 0.0625rem solid rgb(209, 203,203);
color: rgb(66,132,243);
text-align: center;
}
body > .login-form > .line {
border: 0.0625rem solid rgb(209, 209,209);
margin-top: 1rem;
}
body > .login-form > .copyright {
font-size: 0.7rem;
font-weight: 400;
margin-top: 1.5rem;
text-align: center;
}
->
-> Controllers
RootController