Westagram - 2. main page html/css/Js
🌈 Instagram clone코딩을 해보았다.
🌀 main page
📌 main페이지 댓글을 입력할 경우에 댓글창에 댓글이 입력되게 구현
내가 구현해본 main page 👇
✏️ main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=3.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>westagram</title>
<!-- 외부 스타일시트 연결 -->
<link rel="icon" type="image/png" href="imgs/favicon.png" />
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="style.css">
<style type="text/css"></style>
<!-- 외부 스크립트 연결 -->
<script src="index.js" defer></script>
<!-- 폰트어썸 -->
<script src="https://kit.fontawesome.com/684e97b7f2.js" crossorigin="anonymous"></script>
</head>
<!-- body start -->
<body>
<main>
<!-- 헤더 -->
<header>
<nav>
<!-- 로고 -->
<div class="logo">
<div onClick="location.href='#'">
<a><i class="fab fa-instagram"></i></a>
</div>
<div class="wefont">
<h3 class="we"><a>WESTAGRAM</a></h3>
</div>
</div>
<!-- 검색 -->
<div class="searchbar">
<input type="text" placeholder="검색">
</div>
<!-- 아이콘들 -->
<div class="nav">
<div class="navo" onClick="location.href='#'"></div>
<div class="navt" onClick="location.href='#'"></div>
<div class="navh" oncCick="location.href='#'"></div>
</div>
</nav>
</header>
<!-- 인스타그램 피드 & 스토리 -->
<article>
<!-- 인스타그램 피드 -->
<section class="peedleft">
<!-- peedleft의 헤더부분 -->
<div class="top">
<div class="toplogo">
<div class="topimg">
<a><img src="https://i.ibb.co/CQGw903/Kakao-Talk-Image-2021-10-14-18-01-43.jpg" alt=""></a>
</div>
<h4 class="memberid"><a>Cello_daily.0</a></h4>
</div>
<a><i class="fas fa-ellipsis-h"></i></a>
</div>
<!-- 피드이미지 -->
<div class="peedimg"></div>
<!-- 이미지 아래 부분 -->
<div class="peedundericons">
<div class="underleft">
<a><i class="fas fa-heart"></i></a>
<a><i class="far fa-comment"></i></a>
<a><i class="fas fa-external-link-alt"></i></a>
</div>
<div class="underight">
<a><i class="far fa-bookmark"></i></a>
</div>
</div>
<!-- 피드 아이곤 아래 좋아합니다 부분 -->
<div class="peedunderlikes">
<div class="likesleft">
<a><img src="https://i.ibb.co/CQGw903/Kakao-Talk-Image-2021-10-14-18-01-43.jpg" alt=""></a>
<p><a href="#">cookies</a>님 외<a href="#"> 10명이</a> 좋아합니다</p>
</div>
</div>
<!-- 피드 아래 텍스트 부분 -->
<div class="peedtext">
<p class="canon"><a href="#">canon_mj</a> 위워크에서 진행한 베이킹 클래스...<a> 더 보기</a></p>
<div class="id2flexbox">
<p class="id2"><a href="#">neceosecius</a> 거봐 좋았잖아~~~ 🌝 🌝</p>
<a><i class="far fa-heart"></i></a>
</div>
<span class="minit">
<p><a href="#">42분 전</a></p>
</span>
<ul id="commentLists">
<li></li>
</ul>
</div>
<!-- 피드아래 댓글 다는 부분 + 자바스크립트 코드 연동해야하는 부분 -->
<div class="comment">
<input id="name" clss="names" type="text" placeholder="댓글 달기...">
<button class="upload" id="submit">게시</button>
</0>
</div>
</section>
<!-- 인스타그램 오른쪽 스토리부분 -->
<!-- 사이드 오른쪽 부분 -->
<section class="side-right">
<div class="side-container" onclick="location.href='#'">
<div>
</div>
<div>
<div>
<p>wecode_bootcamp<br>
<p>WeCode<span>위코드</span></p>
</div>
</div>
</div>
<div class="side-story">
<div class="side-navigation">
<p>스토리</p>
<div onclick="location.href='#'" class="see-all">
모두 보기
</div>
</div>
<div class="story" onclick="location.href='#'">
<div class="story-img-one"></div>
<div class="story-text">
<p class="bold">god_jaewon</p>
<p class="color">2시간 전</p>
</div>
</div>
<div class="story" onclick="location.href='#'">
<div class="story-img-two"></div>
<div class="story-text">
<p class="bold">soyoon</p>
<p class="color">33분 전</p>
</div>
</div>
<div class="story" onclick="location.href='#'">
<div class="story-img-three"></div>
<div class="story-text">
<p class="bold">ujinSin</p>
<p class="color">10시간 전</p>
</div>
</div>
<div class="story" onclick="location.href='#'">
<div class="story-img-four"></div>
<div class="story-text">
<p class="bold">selina</p>
<p class="color">20분 전</p>
</div>
</div>
</div>
<!-- 추천 시작 -->
<div class="side-pick">
<div class="side-navigation">
<p>회원님을 위한 추천</p>
<div onclick="location.href='#'" class="see-all">
모두 보기
</div>
</div>
<div class="side-wrap">
<div class="sidewraps">
<div class="side-img side-wrap-img1"></div>
<div cass="side-childs">
<p class="name">ockNim</p>
<p class="info">hoo님 외 7명이 팔...</p>
</div>
</div>
<button>팔로우</button>
</div>
<div class="side-wrap">
<div class="sidewraps">
<div class="side-img side-wrap-img2"></div>
<div cass="side-childs">
<p class="name">dragonYong</p>
<p class="info">god_jaewon님 외...</p>
</div>
</div>
<button>팔로우</button>
</div>
<div class="side-wrap">
<div class="sidewraps">
<div class="side-img side-wrap-img3"></div>
<div cass="side-childs">
<p class="name">yeju</p>
<p class="info">Hwayeon 외 4명이...</p>
</div>
</div>
<button>팔로우</button>
</div>
</div>
<div class="footer-wrapper">
<p>Instagram 정보 · 지원 · 홍보센터 · API · <br>채용정보
개인정보처리방침 · 약관 ·<br> 디렉터리 · 프로필 · 해시태그 · 언어</p>
<p>ⓒ 2019 INSTAGRAM</p>
</div>
</section>
</article>
</main>
<script src="index.js" defer></script>
</body>
</html>
✏️ main.css
/* header start */
header {
width: 100%;
height: 90px;
background-color: rgb(255, 255, 255);
border-bottom: 1px solid rgb(235, 233, 233);
position: fixed;
background-color: white;
z-index: 999;
top: 0;
left: 0;
}
nav {
width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
padding-top: 20px;
}
/* header logo */
.logo {
width: 300px;
display: flex;
padding-top: 5px;
}
.logo .fa-instagram {
font-size: 2rem;
color: black;
padding-right: 1.1rem;
border-right: 2px solid black;
}
.logo .wefont {
padding-left: 1rem;
padding-top: 0.3rem;
}
.we {
font-family: 'Lobster', cursive;
color: black;
font-size: 1.6rem;
}
/* 헤더 검색바 */
.searchbar {
width: 250px;
/* position: relative; */
}
.searchbar input {
width: 100%;
padding: 0.5rem 2rem;
margin-top: 6px;
background-color: rgba(238, 235, 235, 0.288);
border: 1px solid rgba(218, 217, 217, 0.767);
}
.searchbar input::placeholder{
font-size: 1rem;
color: silver;
text-align: center;
background: url(https://cdn2.iconfinder.com/data/icons/ios-7-icons/50/search-512.png) no-repeat 35% center/20px 20px;
filter: invert(0.5);
}
input:focus {
outline: 1px solid rgb(179, 179, 179);
}
/* 헤더 우측 아이콘들 */
.nav {
width: 135px;
height: 45px;
display: flex;
justify-content: space-between;
position: relative;
}
.nav div {
display: block;
width: 33px;
/* height: 35px; */
}
.navo{
background: url(https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/explore.png) no-repeat;
background-size: 100%;
background-position: center;
}
.navt {
background: url(https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/heart.png) no-repeat;
background-size: 100%;
background-position: center;
}
.navh {
background: url(https://s3.ap-northeast-2.amazonaws.com/cdn.wecode.co.kr/bearu/profile.png) no-repeat;
background-size: 100%;
background-position: center;
}
.navt::after {
content: "";
display: block;
width: 5px;
height: 5px;
border-radius: 50%;
background-color: red;
position: absolute;
bottom: -5px;
left: 50%;
transform: translateX(-50%);
}
/* 피드 부분 */
article {
width: 1200px;
height: 100%;
margin: 5rem auto;
display: flex;
justify-content: space-between;
}
.peedleft{
width: 66%;
border: 1px solid #e6e6e6;
margin-top: 80px;
}
.topimg img{
width: 40px;
height: 40px;
border-radius: 50%;
}
.top {
display: flex;
justify-content: space-between;
padding: 10px 20px;
}
.toplogo {
display: flex;
}
.memberid a {
margin-top: 15px;
margin-left: 15px;
color: black;
display: block;
}
.fa-ellipsis-h {
color: black;
font-size: 1rem;
margin-top: 15px;
}
.peedimg {
width: 100%;
height: 750px;
background: url(https://i.ibb.co/Np3sttL/10209-D38-C65-C-4-CEC-B871-43459-D788-A06.jpg) no-repeat;
background-size: cover;
background-position: 100%;
}
/* 피드 아이콘들 */
.peedundericons {
display: flex;
padding: 10px 0px;
}
.underleft {
width: 96%;
display: flex;
padding-left: 3px;
}
.underleft a {
display: block;
font-size: 1.5rem;
margin-left: 13px;
color: rgb(145, 145, 145);
}
.underight a {
display: block;
font-size: 1.2rem ;
color: srgb(145, 145, 145);
}
.fa-heart {
color: red;
}
.fa-comment {
transform: rotateY(180deg);
}
.fa-bookmark {
font-size: 1.4rem;
}
/* 좋아요부분 */
.likesleft {
display: flex;
padding: 0 15px;
margin-bottom: 0.5rem;
}
.likesleft img {
width: 25px;
height: 25px;
border-radius: 50%;
}
.likesleft p {
padding-top: 5px;
margin-left: 8px;
font-weight: normal;
}
.likesleft p a {
color: black;
font-weight: 800;
}
/* 댓글 달린 부분 */
.peedtext {
padding-left: 17px;
border-bottom: 1px solid #e6e6e6;
padding-bottom: 10px;
}
.canon {
margin-bottom: 3px;
}
.id2flexbox {
margin-top: 5px;
margin-bottom: 5px;
display: flex;
}
.id2flexbox p {
width: 96%;
}
.id2flexbox>:nth-child(2) i{
color: silver;
}
.minit a{
color: rgb(153, 153, 153);
font-weight: normal;
}
/* form 댓글 다는 부분*/
.comment {
width: 100%;;
position: relative;
}
.comment input {
width: 90%;
border: none;
padding:20px 0;
padding-left: 15px;
}
.comment input:focus {
outline: none;
}
.upload {
padding: 15px 15px;
border: none;
font-size: 0.8rem;
position: absolute;
color: rgba(113, 147, 238, 0.747);
background-color: none;
right: 0px;
top: 6px;
}
.upload:hover {
background: none;;
color: rgba(113, 147, 238, 0.747);
}
#commentLists {
margin-top: 0.6rem;
margin-bottom: 0.7rem;
}
#commentLists li {
width: 100%;
margin-bottom: 0.3rem;
position: relative;
color: black;
}
.delete {
cursor: pointer;
position: absolute;
right: 19px;;
}
.name {
padding-right: 0.6rem;
color: black;
font-weight: bold;
}
/* 피드 오른쪽 스토리 */
.side-right {
width: 368px;
margin-top: 5.3rem;
}
.side-container {
margin-bottom: 1rem;
display: flex;
cursor: pointer;
}
.side-container > :first-child {
width: 60px;
height: 60px;
margin-right: 1rem;
border-radius: 100%;
background: url(https://pbs.twimg.com/profile_images/1109389733912666112/XX55fTPf.jpg)
no-repeat;
background-size: cover;
background-position: center;
}
.side-container > :last-child {
position: relative;
}
.side-container > :last-child div {
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.side-container > :last-child div > :first-child {
margin-bottom: 0.3rem;
font-weight: bold;
}
.side-container > :last-child div > :last-child {
color: #bababa;
}
.side-container > :last-child div > :last-child span:before {
content: "┃";
}
.side-story {
padding: 1rem;
margin-bottom: 1rem;
background: #fff;
border: 1px solid #e6e6e6;
border-radius: 5px;
height: 258px;
overflow-y: hidden;
}
.side-navigation {
margin-bottom: 1rem;
display: flex;
justify-content: space-between;
}
.side-navigation p {
color: #bababa;
}
.see-all {
color: rgb(73, 73, 73);
font-weight: 760;
}
.story {
display: flex;
}
.story > :first-child {
width: 50px;
height: 50px;
margin-right: 1rem;
border: 2px solid #e56c9f;
border-radius: 100%;
}
.side-story > :nth-child(2),
.side-story > :nth-child(3),
.side-story > :nth-child(4) {
margin-bottom: 0.8rem;
}
.story-text {
margin-top: 5px;
}
.story-img-one {
background: url(https://images.unsplash.com/photo-1519764622345-23439dd774f7?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MXx8Ym95c3xlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60)
no-repeat;
background-size: cover;
background-position: top;
}
.story-img-two {
background: url(https://media.istockphoto.com/photos/teen-girl-after-her-vaccination-picture-id1311564458?b=1&k=20&m=1311564458&s=170667a&w=0&h=fK1QViaweFI1OlHtQ6G3S4VrrrMK2lMDrZK-d6yTGms=)
no-repeat;
background-size: cover;
background-position: center;
}
.story-img-three{
background: url(https://images.unsplash.com/photo-1554230505-919a13968970?ixid=MnwxMjA3fDB8MHxzZWFyY2h8M3x8Z2lybHN8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60)
no-repeat;
background-size: cover;
background-position: center;
}
.story-img-four{
background: url(https://images.unsplash.com/photo-1524601500432-1e1a4c71d692?ixid=MnwxMjA3fDB8MHxzZWFyY2h8OXx8Z2lybHN8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60)
no-repeat;
background-size: cover;
background-position: center;
}
.bold {
margin-bottom: 0.3rem;
font-weight: bold;
}
.color {
color: #bababa;
}
/*추천 시작*/
.side-pick {
padding: 1rem;
margin-bottom: 1rem;
background: #fff;
border: 1px solid #e6e6e6;
border-radius: 5px;
position: relative;
}
.side-pick > :nth-child(2),
.side-pick > :nth-child(3) {
margin-bottom: 0.3rem;
}
.side-wrap {
display: flex;
position: relative;
}
.sidewraps {
display: flex;
}
.sidewraps>:last-child {
margin-top: 1rem;
}
.side-img {
width: 50px;
height: 50px;
margin-right: 1rem;
border-radius: 100%;
margin-top: 8px;
}
.side-wrap-img1 {
background: url(https://images.unsplash.com/photo-1502307100811-6bdc0981a85b?ixid=MnwxMjA3fDB8MHxzZWFyY2h8M3x8Ym95c3xlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60)
no-repeat;
background-size: cover;
background-position: center;
}
.side-wrap-img2 {
background: url(https://images.unsplash.com/photo-1613852348851-df1739db8201?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTR8fGJveXN8ZW58MHx8MHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60)
no-repeat;
background-size: cover;
background-position: center;
}
.side-wrap-img3 {
background: url(https://images.unsplash.com/photo-1500336624523-d727130c3328?ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTB8fGdpcmxzfGVufDB8fDB8fA%3D%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=800&q=60)
no-repeat;
background-size: cover;
background-position: center;
}
.side-wrap > :first-child > :last-child > :first-child {
margin-bottom: 0.3rem;
font-weight: bold;
}
.side-wrap > :first-child > :last-child > :last-child {
color: #bababa;
}
.side-wrap > :last-child {
padding: 1.5rem 0 1rem 1rem;
color: #2398ff;
background: none;
position: absolute;
right: 0;
border: none;
font-size: 0.9rem;
font-weight: 700;
}
.footer-wrapper p {
color: #acacac;
line-height: 1.5rem;
margin-bottom: 1rem;
font-weight: 600;
}
✅ css를 작성하면서
👉 처음 인스타그램 클론 코딩을 시작하면서 예시 이미지를 보고 그렇게 어렵지 않겠다고 생각했지만 css를 하면서 생각 했던것보다 할게 많았고 도중에 헷갈렸던 부분들이 조금 있었다. display: flex를 위해서 하나씩 div를 더 감싸주는게 맞을지, position: absolute를 사용해서 div의 갯수를 줄이는게 맞을지 고민했던 것 같다. 결과적으로 나는 이번 westagram에서는 flex를 많이 사용했다.
👉 input창 css에 조금 더 공부하고 알게되는 시간을 가져서 좋았다!. 항상 까다롭다고 생각했었지만 이번에 input에 대해서 공부하면서 생각보다 input을 적용하는데 있어서 조금더 가까워 진것 같다. input에 부모 요소를 하나 더 감싼고 거기에 width값을 준다음에 input의 width: 100%를 한다음 부모 요소에 margin: 0 auto를 하는 방향으로 위치 시켰다.
✏️ main.js
'use strict';
const commentInput = document.getElementById("name");
const submit = document.getElementById("submit");
function checkInput() {
if(!commentInput.value.length) {
alert("댓글을 입력하세요");
}else{
registerComment(commentInput.value);
}
}
function registerComment(value){
const commentLists = document.getElementById("commentLists");
const newCommentList = document.createElement("li");
const newComment = `<span class="name">jiwon</span><span>${value}</span><span class="delete">X</span>`
newCommentList.innerHTML = newComment;
deleteComment(newCommentList);
commentLists.appendChild(newCommentList);
commentInput.value = "";
}
function deleteComment(newCommentList) {
const deleteBtn = newCommentList.querySelector(".delete");
deleteBtn.addEventListener("click", () => newCommentList.remove());
}
commentInput.addEventListener('keyup', () => {
if (window.event.code === 'Enter') {
checkInput();
}else {
submit.addEventListener("click", checkInput);
}
});
// const init = () => {
// submit.addEventListener("click", checkInput);
// };
// init();
const inputId = document.querySelector("#name");
const button = document.querySelector('.upload');
function commentBtn() {
let idValu = inputId.value;
if(idValu.length > 0) {
button.disabled = false;
button.style.cursor = 'pointer';
button.style.color = '#1c7ed6';
} else {
button.disabled = true;
button.style.cursor = 'default';
button.style.color = 'skyblue ';
}
}
inputId.addEventListener('keyup', commentBtn);
✅ js를 작성하면서
👉 댓글창 input에 댓글을 입력하고 '게시'버튼을 눌렀을 경우나 enter키를 쳤을 경우에 댓글이 생성되게 만들어야했다.
그래서 createElement로 새로운 값 li를 생성하게 하고 새로 추가한 li를 innerHTML로 추가하는 함수를 만들었다. 새로 생성된 li를 삭제 할 수도 있게 delete x라는 함수를 만들어서 x를 눌렀을 경우에 댓글이 삭제될 수 있게도 구현해보았다.
🔥 댓글 창 js는 머릿속에서 혼자 생각해내기 힘든 부분들이 있었지만 계속 공부하면서 발전시키고 있다.
Author And Source
이 문제에 관하여(Westagram - 2. main page html/css/Js), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@j-jhoo/Westagram-2.-main-page-htmlcssJs저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)