오늘은 어제에 이어 페이지 연결과 html css javascript 위주로 진행
user가 볼수 있는 main 페이지와 info, cart, order, review의 html 태그와 css 정도는 마무리 하고
main 자바 스크립트나 위치 스타일 마무리
info 페이지도 cs와 js 마무리
main, info는 thymeleaf 받을 태그 정도는 만들어 두고 나중에 controller 쪽 만지면 완료
오늘 배운것 css에서 gap과 sticky, script에서 DOMContentLoaded, getBoundingClientRect()
gap: 10px; 이건 각 항목의 간격을 고르게 주더라고 가운데는 벌어지는데 그걸 일정하게 해줌
position: sticky; 이건 해당 영역을 벗어나면 따라오게 해주는 신기한 명령
DOMContentLoaded, 페이지에서 무든 이벤트가 있을 때마다 감지 이걸 많이 쓰면 렉걸리려나
getBoundingClientRect, 스크롤 감지 관련 문제 때문에 GPT에게 물어가면서 함 GPT 만세
오늘 수정한 코드
main.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8" />
<title></title>
<link href="/css/style.css" rel="stylesheet">
<link href="/css/user/main.css" rel="stylesheet" type="text/css">
<script src="/js/user/main.js" type="text/javascript" defer></script>
</head>
<body>
<div class="innerBox">
<header></header>
<div class="container">
<div class="restaurant-image">
<img src="/images/sample.png" alt="식당 메인 이미지" class="restaurant-img">
</div>
<div class="title">
<div class="restaurant-name">더조은 식당</div>
<button class="report-button button">
<i class="fas fa-exclamation-triangle"></i>신고하기
</button>
</div>
<div class="ratings-reviews">
<div class="ratings">
<div class="stars">★★★★★</div> <!-- 5개의 별을 기본으로 설정 -->
<label>3.3</label> <!-- 예시 평점 -->
</div>
<button class="call-button button">호출하기</button>
</div>
<div class="buttons">
<button class="menu-btn button">메뉴</button>
<button class="announcement-btn button">공지사항</button>
<button class="reviews-btn button">리뷰</button>
</div>
<div class="content">
<div class="menu-content">
<div class="category-content">
<div th:each="category : ${categories}" class="category" th:text="${category.name}" th:data-target="'menu-category-' + ${category.id}"></div>
</div>
<div class="menus-container">
<div th:each="category : ${categories}" class="menu-category" th:id="'menu-category-' + ${category.id}" th:data-category-id="${category.id}" >
<div th:text="${category.name}" class="category-name"></div>
<div class="menus" th:each="menu : ${menus}">
<div th:if="${menu.category.id} == ${category.id}" class="menu" th:onclick="'location.href=\'/user/info?id=' + ${menu.id} + '\''">
<div class="image">
<img src="/images/sample.png" alt="메뉴 이미지" class="restaurant-image">
</div>
<div class="text">
<div th:text="${menu.name}" class="menu-name"></div>
<!--th:text="${menu.info}"-->
<div class="menu-info">맛있음</div>
<div th:text="${menu.price + '원'}" class="menu-price"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="announcement-content">
<div class="announcement">
<div class="title">
<div class="text">공지사항1</div>
<div class="date">16:12</div>
</div>
<div class="content">쉬고싶어서 쉽니다</div>
</div>
<div class="announcement">
<div class="title">
<div class="text">공지사항2</div>
<div class="date">2024.04.03</div>
</div>
<div class="content">아파서 쉽니다</div>
</div>
<div class="announcement">
<div class="title">
<div class="text">공지사항3</div>
<div class="date">2024.04.02</div>
</div>
<div class="content">싱숭생숭해서 쉽니다</div>
</div>
<div class="announcement">
<div class="title">
<div class="text">공지사항4</div>
<div class="date">2024.04.01</div>
</div>
<div class="content">해어져서 쉽니다</div>
</div>
<div class="announcement">
<div class="title">
<div class="text">공지사항5</div>
<div class="date">2024.03.20</div>
</div>
<div class="content">그냥 쉽니다</div>
</div>
</div>
<div class="review-content" >
<div class="review">
<div class="title">박윤재</div>
<div class="mid">
<!-- 여기에 별점을 표시할 div를 추가합니다. 데이터 속성(data-rating)을 사용하여 별점을 지정합니다. -->
<div class="star" data-rating="5"></div>
<div class="date">1달전</div>
</div>
<div class="content">음식이 친절하고 사장님이 맛있어요</div>
</div>
<div class="review">
<div class="title">손지영</div>
<div class="mid">
<div class="star" data-rating="4"></div>
<div class="date">2024.04.01</div>
</div>
<div class="content">1주전</div>
</div>
<div class="review">
<div class="title">윤경재</div>
<div class="mid">
<div class="star" data-rating="1"></div>
<div class="date">2시간전</div>
</div>
<div class="content">집에 보내주세요</div>
</div>
</div>
</div>
</div>
<footer></footer>
<!-- 신고하기 모달 창 -->
<div id="reportModal" class="modal report-modal">
<div class="modal-content">
<h2 class="modal-title">가게 신고</h2>
<p class="modal-warning">가게 신고 시 돌이킬 수 없으며,<br>허위로 신고를 작성한 경우<br>신고는 무효화 됩니다.</p>
<label for="reportReason" class="modal-label">신고 사유</label>
<textarea id="reportReason" class="modal-input"></textarea>
<button class="modal-submit button" id="reportCall">신고하기</button>
</div>
</div>
<!-- 호출하기 모달 창 -->
<div id="callModal" class="modal call-modal">
<div class="modal-content">
<h2 class="modal-title">호출하기</h2>
<form id="callForm">
<label><input type="radio" name="callOption" value="water" checked/> 물 주세요</label><br />
<label><input type="radio" name="callOption" value="cup" /> 컵 주세요</label><br />
<label><input type="radio" name="callOption" value="towel" /> 물수건 주세요</label><br />
<label><input type="radio" name="callOption" value="staff" /> 그냥 직원오세요</label>
</form>
<button class="modal-submit button" id="submitCall">호출하기</button>
</div>
</div>
</div>
</body>
</html>
main.css
@charset "UTF-8";
/* 메인 이미지 */
.container .restaurant-image{
width: 100%;
height: 200px;
overflow: hidden;
}
.container .restaurant-image img{
width: 100%;
height: auto;
object-fit: cover;
object-position: center top;
}
/* 타이틀과 신고버튼 */
.container .title{
width: 100%;
padding: var(--padding);
display: flex;
justify-content: space-between;
align-items: center;
}
/* 타이틀 */
.container .title .restaurant-name{
font-size: var(--font-big);
font-weight: bold;
}
/* 신고 */
.container .title .report-button{
padding: 0;
background-color: transparent;
color: red;
border: none;
font-size: var(--font-small);
}
.container .title .report-button .fa-exclamation-triangle{
margin-right: 5px;
}
/* 별표와 리뷰 버튼*/
.container .ratings-reviews{
margin-bottom: 10px;
padding: var(--padding);
padding-top: 0;
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
/* 별표 부분*/
.container .ratings-reviews .ratings {
display: flex;
align-items: center;
}
/* 별표의 별 부분 */
.container .ratings-reviews .ratings .stars{
position: relative;
display: inline-block;
font-size: 20px; /* 별 크기 조정 */
direction: rtl; /* 별을 오른쪽에서 왼쪽으로 채워나가기 위해 */
}
.container .ratings-reviews .ratings .stars::after{
content: "★★★★★";
color: lightgray; /* 기본 별 색상 설정 */
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 0;
}
.star-fill {
display: block;
color: gold; /* 금색 별 색상 설정 */
position: absolute;
top: 0;
left: 0;
overflow: hidden;
z-index: 1;
direction: ltr; /* 금색 별이 왼쪽에서 시작하도록 설정 */
}
/* 별표의 숫자 부분 */
.container .ratings-reviews .ratings label{
margin-left: 10px;
}
/* 호출 버튼 부분*/
.container .ratings-reviews .call-button{
border: 0;
border-radius: 0;
padding: 10px 30px;
}
/* 메뉴 공지사항 리뷰 */
.container .buttons{
border-bottom: 3px solid var(--orange);
display: flex;
width: 100%;
}
/* 메뉴 */
.container .buttons .menu-btn{
border: 0;
border-radius: 0;
flex: 1;
font-size: var(--font-content);
padding: var(--padding);
}
/* 공지사항 */
.container .buttons .announcement-btn{
background-color: inherit;
color: var(--gray);
border: 0;
border-radius: 0;
flex: 1;
font-size: var(--font-content);
padding: var(--padding);
}
/* 리뷰 */
.container .buttons .reviews-btn{
background-color: inherit;
color: var(--gray);
border: 0;
border-radius: 0;
flex: 1;
font-size: var(--font-content);
padding: var(--padding);
}
/* 버튼을 눌렀을때 보여주는 콘텐츠 영역 */
.container .content{
width: 100%;
}
/* 메뉴 콘텐츠 */
.container .content .menu-content{
width: 100%;
}
/* 카테고리 슬라이더 부분 */
.container .content .menu-content .category-content{
width: 100%;
display: flex; /* 이 부분을 추가합니다 */
overflow-x: auto; /* 수평 스크롤을 위해 추가합니다 */
background-color: var(--white);
scrollbar-width: none;
position: sticky;
top: 0; /* 상단에 고정 */
z-index: 1; /* 다른 요소들 위에 오도록 z-index 설정 */
}
.container .content .menu-content .category-content .category{
margin: 10px;
padding: 10px 20px;
flex: 0 0 auto; /* flex 항목이 자신의 크기를 유지하도록 설정합니다 */
border-radius: 20px;
text-align: center;
background-color: var(--white);
color:var(--black);
cursor: pointer; /* 마우스 오버 시 커서 변경을 위해 추가합니다 */
border: 1px solid var(--gray);
transition: background-color 0.3s, color 0.3s; /* 부드러운 색상 전환 */
}
.container .content .menu-content .category-content .category.active{
background-color: var(--gray);
color: var(--white);
}
.container .content .menu-content .category-content:last-child{
margin-right: 0;
}
/* 메뉴 리스트 */
.container .content .menu-content .menus-container {
}
.container .content .menu-content .menus-container .category-name{
padding:var(--padding);
background-color: var(--extra-light-gray);
color: var(--gray);
font-size: var(--font-middle);
font-weight: bold;
border-bottom: 2px solid var(--light-gray);
}
.container .content .menu-content .menus-container .menu{
width: 100%;
display: flex;
border-bottom: 2px solid var(--light-gray);
}
.container .content .menu-content .menus-container .menu .image{
padding: 10px;
width: 120px;
height: 120px;
overflow: hidden;
}
.container .content .menu-content .menus-container .menu .image img{
width: 100%;
height: 100%;
}
.container .content .menu-content .menus-container .menu .text{
padding: 10px;
display: flex;
flex-direction: column;
}
.container .content .menu-content .menus-container .menu .text .menu-name{
margin-bottom: 10px;
font-size: var(--font-content);
font-weight: bold;
color:var(--black);
}
.container .content .menu-content .menus-container .menu .text .menu-info{
margin-bottom: 10px;
flex: 1;
font-size: var(--font-content);
color:var(--gray);
}
.container .content .menu-content .menus-container .menu .text .menu-price{
font-size: var(--font-content);
color:var(--black);
}
/* 공지사항 콘텐츠 */
.container .content .announcement-content{
width: 100%;
display: none;
}
.container .content .announcement-content .announcement {
width: 100%;
display: flex;
flex-direction: column;
padding: 20px;
border-bottom: 2px solid var(--light-gray);
}
.container .content .announcement-content .announcement .title {
padding:0;
font-size: var(--font-middle);
color: var(--black);
margin-bottom: 20px;
}
.container .content .announcement-content .announcement .date{
padding:0;
font-size: var(--font-small);
color: var(--light-gray);
}
.container .content .announcement-content .announcement .content{
padding:0;
font-size: var(--font-content);
color: var(--gray);
}
/* 리뷰 */
.container .content .review-content{
width: 100%;
display: none;
padding: var(--padding);
}
.container .content .review-content .review{
margin-bottom: 20px;
box-sizing: border-box;
display: flex;
flex-direction: column;
border: 2px solid var(--light-gray);
padding: var(--padding);
}
.container .content .review-content .review .title{
padding: 0;
font-size: var(--font-content);
color: var(--black);
}
.container .content .review-content .review .mid{
display: flex;
font-size: var(--font-small);
color: var(--light-gray);
flex: 1;
padding-bottom: 20px;
}
.container .content .review-content .review .mid .star{
font-size: var(--font-small); /* 별의 크기 조절 */
color: #ccc; /* 기본 별 색상 (회색) */
position: relative; /* 상대적 위치 설정 */
margin-right: 20px;
}
.container .content .review-content .review .mid .star span.filled {
color: gold; /* 노란색 별 */
}
.container .content .review-content .review .mid .star span.empty {
color: #ccc; /* 회색 별 */
}
.container .content .review-content .review .mid .date{}
.container .content .review-content .review .content{
font-size: var(--font-content);
color: var(--black);
}
/* 모달 창 스타일 */
.modal {
display: none; /* 초기에는 숨김 */
position: absolute; /* 화면 중앙에 위치 */
z-index: 1; /* 내용 위에 표시 */
left: 0;
top: 0;
width: 100%; /* 전체 너비 */
height: 100%; /* 전체 높이 */
overflow: auto; /* 내용이 넘칠 경우 스크롤 */
background-color: rgb(0,0,0); /* 검은색 배경 */
background-color: rgba(0,0,0,0.4); /* 어두운 투명도 */
}
/* 모달 내용 스타일 */
.modal-content {
background-color: #fefefe;
margin: 15% auto; /* 페이지 중앙에 위치 */
padding: 20px;
border: 1px solid #888;
width: 300px; /* 너비 설정 */
height: 300px; /* 높이 설정 */
display: flex;
flex-direction: column;
justify-content: space-between;
}
.modal-title {
text-align: center;
font-weight: bold;
}
.modal-warning {
color: red;
text-align: center;
}
.modal-label {
text-align: left;
}
.modal-input {
width: 100%;
height: 100px;
}
.modal-submit {
background-color: #222; /* 검은색 배경 */
color: #fff; /* 하얀색 글씨 */
text-align: center;
}
main.js - 여기서 별 구현은 GPT의 힘을 많이 빌림
const menu = document.querySelector(".menu-btn");
const announcement = document.querySelector(".announcement-btn");
const reviews = document.querySelector(".reviews-btn");
const menuContent = document.querySelector('.menu-content');
const announcementContent = document.querySelector('.announcement-content');
const reviewContent = document.querySelector('.review-content');
/* 식당 평점 별 부분*/
document.addEventListener('DOMContentLoaded', function() {
var ratings = document.querySelectorAll('.ratings');
ratings.forEach(function(rating) {
var stars = rating.querySelector('.stars');
var label = rating.querySelector('label');
var ratingValue = parseFloat(label.textContent);
var starPercentage = (ratingValue / 5) * 100; // 평점을 백분율로 변환
var starPercentageRounded = `${parseFloat(starPercentage.toFixed(1))}%`; // 첫 번째 소수점 자리까지 표시
// 금색 별을 표시할 span 요소 생성 및 스타일 설정
var starFill = document.createElement('span');
starFill.className = 'star-fill';
starFill.style.width = starPercentageRounded;
starFill.innerHTML = '★★★★★'; // 금색 별
// 기존 별점 요소를 클리어하고, 금색 별 span과 기본 별을 추가
stars.innerHTML = ''; // 기존 내용을 클리어
stars.appendChild(starFill); // 금색 별 추가
stars.innerHTML += '★★★★★'; // 기본 별 추가 (회색 별)
});
});
/* 메뉴 버튼 클릭 시 */
menu.addEventListener('click', () => {
menu.style.backgroundColor = '#ff7a2f';
announcement.style.backgroundColor = 'inherit';
reviews.style.backgroundColor = 'inherit';
menu.style.color = '#fff';
announcement.style.color = '#717171';
reviews.style.color = '#717171';
menuContent.style.display = 'block';
announcementContent.style.display = 'none';
reviewContent.style.display = 'none';
});
/* 공지사항 버튼 클릭 시 */
announcement.addEventListener('click', () => {
menu.style.backgroundColor = 'inherit';
announcement.style.backgroundColor = '#ff7a2f';
reviews.style.backgroundColor = 'inherit';
menu.style.color = '#717171';
announcement.style.color = '#fff';
reviews.style.color = '#717171';
menuContent.style.display = 'none';
announcementContent.style.display = 'block';
reviewContent.style.display = 'none';
});
/* 리뷰 버튼 클릭 시 */
reviews.addEventListener('click', () => {
menu.style.backgroundColor = 'inherit';
announcement.style.backgroundColor = 'inherit';
reviews.style.backgroundColor = '#ff7a2f';
menu.style.color = '#717171';
announcement.style.color = '#717171';
reviews.style.color = '#fff';
menuContent.style.display = 'none';
announcementContent.style.display = 'none';
reviewContent.style.display = 'block';
});
// 신고 버튼 클릭 이벤트
document.querySelector('.report-button').addEventListener('click', () => {
document.getElementById('reportModal').style.display = 'block';
});
// 신고하기 버튼 클릭 이벤트로 모달 창 닫기 (옵션)
document.querySelector('.modal-submit').addEventListener('click', () => {
document.getElementById('reportModal').style.display = 'none';
});
// 호출하기 버튼 클릭 이벤트
document.querySelector('.call-button').addEventListener('click', () => {
document.getElementById('callModal').style.display = 'block';
});
// 호출하기 모달에서 호출하기 버튼 클릭 이벤트
document.getElementById('submitCall').addEventListener('click', () => {
// 실제 애플리케이션에서는 이곳에 선택된 옵션을 처리하는 로직을 구현합니다.
// 예: 선택된 라디오 버튼의 값을 서버로 전송
console.log('호출 옵션:', document.querySelector('input[name="callOption"]:checked').value);
document.getElementById('callModal').style.display = 'none'; // 모달 닫기
});
// 모달 창 밖을 클릭할 때 모달 창 닫기
window.addEventListener('click', e => {
if (e.target.classList.contains('modal')) {
e.target.style.display = 'none';
}
});
// 슬라이더 부분
document.addEventListener('DOMContentLoaded', function() {
const slider = document.querySelector('.category-content');
let isDown = false;
let startX;
let scrollLeft;
slider.addEventListener('mousedown', (e) => {
isDown = true;
slider.classList.add('active');
startX = e.pageX - slider.offsetLeft;
scrollLeft = slider.scrollLeft;
});
slider.addEventListener('mouseleave', () => {
isDown = false;
slider.classList.remove('active');
});
slider.addEventListener('mouseup', () => {
isDown = false;
slider.classList.remove('active');
});
slider.addEventListener('mousemove', (e) => {
if(!isDown) return;
e.preventDefault();
const x = e.pageX - slider.offsetLeft;
const walk = (x - startX) * 3; //scroll-fast
slider.scrollLeft = scrollLeft - walk;
});
});
document.addEventListener('DOMContentLoaded', function() {
const categories = document.querySelectorAll('.category');
const menuContainers = document.querySelectorAll('.menu-category');
const categoryContent = document.querySelector('.category-content');
// 현재 활성화된 카테고리를 표시하고 스크롤 시 갱신
function setActiveCategory() {
let currentActiveIndex = 0;
menuContainers.forEach((container, index) => {
const containerTop = container.getBoundingClientRect().top;
if (containerTop - window.innerHeight / 2 < 0) {
currentActiveIndex = index;
}
});
categories.forEach((category, index) => {
if (index === currentActiveIndex) {
category.classList.add('active');
} else {
category.classList.remove('active');
}
});
}
// 클릭한 카테고리가 화면에 완전히 보이지 않을 경우 스크롤
function ensureCategoryVisible(category) {
const categoryRect = category.getBoundingClientRect();
const containerRect = categoryContent.getBoundingClientRect();
if (categoryRect.left < containerRect.left) {
// 카테고리 버튼이 뷰포트 왼쪽 밖에 위치한 경우
categoryContent.scrollLeft -= (containerRect.left - categoryRect.left) + 20; // 여백 추가
} else if (categoryRect.right > containerRect.right) {
// 카테고리 버튼이 뷰포트 오른쪽 밖에 위치한 경우
categoryContent.scrollLeft += (categoryRect.right - containerRect.right) + 20; // 여백 추가
}
}
// 카테고리 클릭 이벤트
categories.forEach(category => {
category.addEventListener('click', function() {
const targetId = this.getAttribute('data-target');
const targetElement = document.getElementById(targetId);
if (targetElement) {
// category-content의 높이를 가져옵니다.
const categoryContentHeight = document.querySelector('.category-content').offsetHeight;
// targetElement까지의 절대 위치를 계산합니다.
const elementPosition = targetElement.getBoundingClientRect().top + window.pageYOffset;
// category-content의 높이만큼 위치를 조정합니다.
const offsetPosition = elementPosition - categoryContentHeight;
// 계산된 위치로 스크롤합니다.
window.scrollTo({
top: offsetPosition,
behavior: "smooth"
});
}
});
});
// 스크롤 이벤트
window.addEventListener('scroll', setActiveCategory);
// 초기 활성화 카테고리 설정
setActiveCategory();
});
// 리뷰 별점 정수값을 별 개수로 표시하는
document.addEventListener('DOMContentLoaded', function() {
const reviewStars = document.querySelectorAll('.review .star');
reviewStars.forEach(function(star) {
const rating = parseInt(star.getAttribute('data-rating'));
let starsText = '★★★★★';
// 노란색 별을 표시할 부분과 회색 별을 표시할 부분을 결정
let filledStars = starsText.slice(0, rating).replace(/★/g, '<span class="filled">★</span>');
let emptyStars = starsText.slice(rating).replace(/★/g, '<span class="empty">★</span>');
// 별점을 HTML로 설정
star.innerHTML = filledStars + emptyStars;
});
});
info.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title></title>
<link href="/css/style.css" rel="stylesheet">
<link href="/css/user/info.css" rel="stylesheet" type="text/css">
<script src="/js/user/info.js" type="text/javascript" defer></script>
</head>
<body>
<div class="innerBox">
<header></header>
<div class="container">
<form action="/user/info" method="post" class="info-form">
<div class="menu-image">
<img src="/images/sample.png" alt="음식 이미지" class="menu-img">
</div>
<div class="info">
<div class="info-title">짜파게티</div>
<div class="info-contents">맛있는 짜파게티 김치 미포함</div>
<div class="info-price">300원</div>
</div>
<div class="option">
<div class="option-title">
<div class="option-title-text">매운맛</div>
<div class="option-title-select">필수</div>
</div>
<div class="option-contents">
<div class="option-contents-select">
<input type="radio" name="spiciness" class="option-check" value="spicy">
<span class="option-contents-content">맵게 해주세요</span>
<span class="option-contents-price">+3000원</span>
</div>
<div class="option-contents-select">
<input type="radio" name="spiciness" class="option-check" value="not-spicy">
<span class="option-contents-content">안맵게 해주세요</span>
<span class="option-contents-price">+4000원</span>
</div>
</div>
</div>
<div class="option">
<div class="option-title">
<div class="option-title-text">토핑</div>
<div class="option-title-select">선택</div>
</div>
<div class="option-contents">
<div class="option-contents-select">
<input type="checkbox" class="option-check">
<span class="option-contents-content">치즈</span>
<span class="option-contents-price">1000원</span>
</div>
<div class="option-contents-select">
<input type="checkbox" class="option-check">
<span class="option-contents-content">감자</span>
<span class="option-contents-price">1000원</span>
</div>
</div>
</div>
<div class="white-gap"></div>
<div class="count">
<div class="count-inner">
<div class="count-text">수량</div>
<div class="count-button">
<input type="button" class="minus" value="-">
<div class="text">1</div>개
<input type="button" class="plus" value="+">
</div>
</div>
<input type="button" class="submit button" value="300원 담기" onclick="infosubmit(form)">
</div>
</form>
</div>
<footer></footer>
</div>
</body>
</html>
info.css
@charset "UTF-8";
.container form{
width: 100%;
margin: 0;
padding: 0;
}
/* 메인 사진 */
.container .menu-image{
width: 100%;
height: 250px;
overflow: hidden;
}
.container .menu-image img{
width: 100%;
height: auto;
object-fit: cover;
object-position: center top;
}
/* 음식 설명 */
.container .info{
padding: var(--padding);
margin: 0;
display: flex;
flex-direction: column;
position: relative;
}
.container .info .info-title{
font-size: var(--font-big);
font-weight: bold;
margin-bottom: 10px;
color: var(--black);
}
.container .info .info-contents{
font-size: var(--font-small);
color: var(--light-gray);
}
.container .info .info-price{
font-size: var(--font-middle);
color: var(--black);
text-align: right;
}
/* 옵션 */
.container .option{
margin: 0;
display: flex;
flex-direction: column;
}
.container .option .option-title{
padding: var(--padding);
width: 100%;
display: flex;
justify-content: space-between;
background-color: var(--extra-light-gray);
color: var(--light-gray);
}
.container .option .option-title .option-title-text{
padding: 10px;
color: var(--gray);
}
.container .option .option-title .option-title-select{
padding: 10px;
background-color: var(--light-gray);
color: var(--gray);
}
.container .option .option-title .option-title-select .option-check{
margin-right: 10px;
}
.container .option .option-title .option-title-select .option-contents-content{
margin: 10px 0;
}
.container .option .option-contents{
padding: var(--padding);
width: 100%;
display: flex;
flex-direction: column;
}
.container .option .option-contents .option-contents-select{
display: flex;
margin-bottom: 10px; /* 마지막 요소를 제외하고 각 요소의 하단에 간격 추가 */
}
.container .option .option-contents .option-contents-select:last-child {
margin-bottom: 0; /* 마지막 요소는 하단 간격 제거 */
}
.container .option .option-contents .option-contents-select .option-contents-content{
flex: 1;
}
/* count 때문에 넣는 빈공간 */
.container .white-gap{
width: 100%;
height: var(--fixedBtn-height);
}
/* 수량 */
.container .count {
position: fixed;
left: 50%;
bottom: 0;
margin: 0;
/* 자신의 너비의 반만큼 왼쪽으로 이동하여 정확히 중앙에 위치하도록 조정 */
transform: translateX(-50%);
width: var(--innerBox-width);
background-color: white;
z-index: 1; /* 필요에 따라 조정 */
padding: var(--padding);
}
.container .count .count-inner{
display: flex;
justify-content: space-between; /* 내부 요소를 양 끝으로 정렬 */
width: 100%; /* 부모 컨테이너의 전체 너비 사용 */
padding: 0 20px; /* 좌우 패딩 추가로 내부 요소들 사이 간격 조정 */
margin-bottom: 10px;
}
.container .count .count-inner .count-text {
font-size: var(--font-content); /* 필요에 따라 조정 */
color: var(--black);
display: flex;
justify-content: center;
align-items: center;
}
.container .count .count-inner .count-button {
padding: 5px;
display: flex;
justify-content: right;
border: 2px solid var(--light-gray);
}
.container .count .count-inner .count-button .minus,
.container .count .count-inner .count-button .plus{
padding: 0 15px;
display: flex;
justify-content: center;
align-items: center;
border: 0;
background-color: var(--white);
font-size: var(--font-content); /* 버튼 내 텍스트 크기 */
cursor: pointer; /* 마우스 커서 변경 */
}
.container .count .count-inner .count-button .text{
display: flex;
justify-content: center;
align-items: center;
font-size: var(--font-content); /* 필요에 따라 조정 */
}
/* 버튼 */
.container .count .submit{
width: calc(100% - 20px); /* 패딩 고려하여 너비 조정 */
}
info.js
/* form 하기 전에 체크 */
function infosubmit(form) {
form.submit();
}
const ocs = document.querySelectorAll('.option-contents-select');
ocs.forEach(select => {
select.addEventListener('click', e => {
// 'this' 대신 'select' 사용
const input = select.querySelector('input[type=checkbox], input[type=radio]');
if (e.target !== input) {
input.checked = !input.checked;
// 라디오 버튼의 경우, 다른 라디오 버튼의 상태 변경을 위해 이벤트를 발생시킵니다.
input.dispatchEvent(new Event('change'));
}
});
});
이제 메인은 반응형 하고 값 제대로 안들어갈때나 건드릴듯
기능 참 많네
'공부 > Ganju' 카테고리의 다른 글
| [Spring/AWS] 팀프로젝트 8일차 (0) | 2024.04.06 |
|---|---|
| [Spring/AWS] 팀프로젝트 7일차 (0) | 2024.04.04 |
| [Spring/AWS] 팀프로젝트 5일차 (0) | 2024.04.02 |
| [Spring/AWS] 팀프로젝트 4일차 (0) | 2024.04.02 |
| [Spring/AWS] 팀프로젝트 3일차 (0) | 2024.03.29 |






