<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Westagram</title>
<link rel=stylesheet href="style/main.css">
<link rel=stylesheet href="style/common.css">
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
<script src="https://kit.fontawesome.com/e2f453cbbf.js"></script>
</head>
<body>
<div class="nav">
<div class="nav_logo"">
<a href="main.html"><i class="fab fa-instagram"></i>
<span class="nav_logo_name">Westagram</span></a>
</div>
<div class="nav_search">
<input placeholder="검색">
<div class="search_plus">
<div class="search_plus_nav">
<div>최근 검색 항목</div>
<div>모두 지우기</div>
</div>
<div class="search_plus_article">
<div class="search_plus_profile">
<div class="search_plus_photo">
<img alt="wecoder_photo" src="/img/wecode.jpeg">
</div>
<div class="search_plus_info">
<div class="search_plus_id">wecode_bootcamp</div>
<div class="search_plus_name">WeCode | 위코드</div>
</div>
</div>
</div>
</div>
<i class="fas fa-search" id="search_icon"></i>
</div>
<div class="nav_icons">
<img alt="explore" class="nav_icon" src="img/explore.png">
<img alt="my_profile" class="nav_icon" src="img/profile.png" id="my_profile">
<div class="my_profile_plus">
<li><div><i class="far fa-user-circle"></i></div><div>프로필</div></li>
<li><div><i class="far fa-bookmark"></i></div><div>저장됨</div></li>
<li><div><i class="fas fa-cog"></i></div><div>설정</div></li>
<li><div><i class="fas fa-exchange-alt"></i></div><div>계정 전환</div></li>
<li class="my_profile_logout">로그아웃</li>
</div>
<img alt="news" class="nav_icon" src="img/heart.png">
</div>
</div>
<main>
<div class="feeds">
<div class="article">
<div class="profile_box">
<div class="profile">
<div>
<img alt="my_profile" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="username">
<strong>code_bootcamp</strong>
</div>
</div>
<div>
<i class="fas fa-ellipsis-h"></i></div>
</div>
<div class="feed">
<img alt="feed_photo" class="feed_photo" src="img/main.jpeg">
</div>
<div class="feed_bottom">
<div class="feed_icons">
<div>
<i class="far fa-heart" id="love"></i>
<i class="far fa-comment"></i>
<i class="far fa-paper-plane"></i>
</div>
<div id="bookmark"><i class="far fa-bookmark"></i></div>
</div>
<div class="feed_likes">
<strong>CSS</strong>님 외 3명이좋아합니다
</div>
<div class="feed_text">
<strong>wecode_bootcamp</strong> 안녕하세요<br>
</div>
<div class="comment_box">
<div class="comment">
<div><b>html</b> 멋져요🛶</div><div><i class="fas fa-times"></i><i class="far fa-heart"></i></div>
</div>
<div class="comment">
<div><b>java</b> 이뻐요🚀</div><div><i class="fas fa-times"></i><i class="far fa-heart"></i></div>
</div>
</div>
<div class="feed_time">
12분전
</div>
</div>
<div class="comment_input_box">
<input class="comment_input" type="text" placeholder="댓글 달기...">
<span class="comment_enter">게시</span>
</div>
</div>
</div>
<aside>
<div class="main_right">
<div class="my_profile">
<div class="my_photo">
<img alt="wecoder_photo" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="my_info">
<div class="my_id">wecode_bootcamp</div>
<div class="my_name">WeCode | 위코드</div>
</div>
</div>
<div class="story">
<div class="story_nav">
<div>스토리</div>
<div>모두보기</div>
</div>
<div class="story_peeds">
<div class="story_peed">
<div class="story_photo">
<img alt="wecoder_photo" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="stoty_info">
<div class="username">JAVA</div>
<div class="feed_time">1분 전</div>
</div>
</div>
<div class="story_peed">
<div class="story_photo">
<img alt="wecoder_photo" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="stoty_info">
<div class="username">HTML</div>
<div class="feed_time">48분 전</div>
</div>
</div>
<div class="story_peed">
<div class="story_photo">
<img alt="wecoder_photo" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="stoty_info">
<div class="username">react</div>
<div class="feed_time">21분 전</div>
</div>
</div>
<div class="story_peed">
<div class="story_photo">
<img alt="wecoder_photo" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="stoty_info">
<div class="username">code</div>
<div class="feed_time">42분 전</div>
</div>
</div>
<div class="story_peed">
<div class="story_photo">
<img alt="wecoder_photo" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="stoty_info">
<div class="username">dsfnl2</div>
<div class="feed_time">24분 전</div>
</div>
</div>
<div class="story_peed">
<div class="story_photo">
<img alt="wecoder_photo" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="stoty_info">
<div class="username">fds2</div>
<div class="feed_time">16분 전</div>
</div>
</div>
<div class="story_peed">
<div class="story_photo">
<img alt="wecoder_photo" class="user_photo" src="img/wecode.jpeg">
</div>
<div class="stoty_info">
<div class="username">wecoder</div>
<div class="feed_time">10분 전</div>
</div>
</div>
</div>
</div>
<div class="recommend">
<div class="story_nav">
<div>회원님을 위한 추천</div>
<div>모두보기</div>
</div>
<div class="recommend_peeds">
<div class="recommend_peed">
<div class="recommend_photo">
<img alt="wecoder_photo"src="img/wecode.jpeg" class="user_photo">
</div>
<div class="recommend_info">
<div>
<div class="username">have</div>
<div class="feed_time">8명이 팔로우</div>
</div>
<div class="follow">팔로우</div>
</div>
</div>
<div class="recommend_peed">
<div class="recommend_photo">
<img alt="wecoder_photo"src="img/wecode.jpeg" class="user_photo">
</div>
<div class="recommend_info">
<div>
<div class="username">have</div>
<div class="feed_time">7명이 팔로우</div>
</div>
<div class="follow">팔로우</div>
</div>
</div>
<div class="recommend_peed">
<div class="recommend_photo">
<img alt="wecoder_photo"src="img/wecode.jpeg" class="user_photo">
</div>
<div class="recommend_info">
<div>
<div class="username">have</div>
<div class="feed_time">6명이 팔로우</div>
</div>
<div class="follow">팔로우</div>
</div>
</div>
<div class="recommend_peed">
<div class="recommend_photo">
<img alt="wecoder_photo"src="img/wecode.jpeg" class="user_photo">
</div>
<div class="recommend_info">
<div>
<div class="username">have</div>
<div class="feed_time">2명이 팔로우</div>
</div>
</div>
<div class="follow">팔로우</div>
</div>
</div>
</div>
<footer>
instagram 정보 · 지원 · 홍보 센터 · API · 채용정보 · 개인정보처리방침 · 약관 · 다렉터리 · 프로필 · 해시태그 · 언어
<br>© 2021 INSTAGRAM FROM FACEBOOK
</footer>
</div>
</aside>
</main>
<script src='js/main.js'></script>
</body>
</html>
아직도 이름에 마음이 들진 않지만 전에는 더 심각했다.
처음에 빠르게 완성만 시키자는 생각으로 이름, 태그들을 너무 대충 지었는데
리팩토링할 때 시간이 몇 시간 걸렸다.. (처음부터 잘하자 !)
완성될 때쯤 코드가 너무 지저분하고 레이아웃도 너무 이상했다.
이래서 html, css가 중요하다는 걸 다시 한번 깨달았다.
이름도 의미가 너무 없어 다시 짓고 필요 없는 코드도 정리했다.
i:hover {
cursor: pointer;
}
li {
list-style: none;
}
.nav {
width: 100%;
height: 50px;
padding: 0 125px;
border-bottom: rgb(219, 219, 219) 1px solid;
background-color: white;
font-size: 35px;
display: flex;
justify-content: space-around;
text-align: center;
position: fixed;
top: 0;
z-index: 1;
}
.nav_logo {
margin: auto 0;
}
.nav_logo i {
margin-right: 20px;
color: black;
}
.nav_logo_name {
font-family: 'Lobster', cursive;
color: black;
}
.nav_search {
width: 200px;
}
.nav_search input {
height: 25px;
width: 100%;
background-color: #FAFAFA;
border: rgb(219, 219, 219) 1px solid;
border-radius: 3px;
text-indent: 95px;
}
#search_icon {
font-size: 12px;
color: #A4A7AA;
position: relative;
bottom: 43px;
right: 13px;
}
.search_plus {
width: 375px;
height: 360px;
font-size: 25px;
position: relative;
background-color: white;
display: none;
overflow: scroll;
flex-direction: column;
border : gray 1px solid;
border-radius: 10px;
padding: 15px;
float:right;
}
.search_plus::-webkit-scrollbar {
display: none;
}
.search_plus_nav {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
font-size: 15px;
}
.search_plus_article {
display: flex;
flex-direction: column;
}
.search_plus_profile {
display: flex;
}
.search_plus_profile img {
width: 44px;
height: 44px;
border-radius: 50%;
margin-right: 20px;
}
.search_plus_info {
font-size: 13px;
}
.nav_icon {
width: 30px;
height: 30px;
margin: 10px;
}
.my_profile_plus{
flex-direction: column;
z-index: 1;
background-color: white;
border: black 1px solid;
font-size: 18px;
border-radius: 8px;
position: fixed;
display: none;
left: 1000px;
}
.my_profile_plus li{
display: flex;
padding: 10px;
width: 230px;
}
.my_profile_plus li:hover{
background-color: gray;
cursor: pointer;
border-radius: 4px;
}
.my_profile_plus i{
margin-right: 20px;
width: 33px;
}
.my_profile_logout{
border-top: 1px gray solid;
width: 33px;
}
.nav_icons img:hover{
cursor: pointer;
}
main {
background-color:#FAFAFA;
padding: 100px 223px;
display: flex;
}
.feeds {
height: 100%;
width: 615px;
border: 1px rgb(219, 219, 219) solid;
border-radius: 3px;
margin-right: 40px;
}
.article {
width: 100%;
height: 1100px;
border-radius: 3px;
background-color: white;
display: flex;
flex-direction: column;
}
.profile_box {
width: 100%;
height: 60px;
display: flex;
justify-content: space-between;
}
.profile_box i {
margin: 20px;
font-size: 20px;
}
.profile .user_photo {
width: 35px;
height: 35px;
border-radius: 50%;
margin: 13px;
}
.profile {
display: flex;
text-align: center;
}
.profile .username {
font-size: 15px;
margin: auto 0;
}
.feed {
width: 100%;
height: 100%;
}
.feed_photo {
width: 100%;
height: 100%;
}
.feed_bottom {
height: 250px;
padding: 15px;
font-size: 15px;
border-bottom: 1px rgb(219, 219, 219) solid;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.feed_icons {
display: flex;
justify-content: space-between;
font-size: 25px;
margin-bottom: 5px;
}
.feed_icons i {
padding-right: 10px;
}
#bookmark i {
padding: 0;
}
.feed_likes {
margin-bottom: 10px;
}
.feed_time{
color: gray;
font-size: 12px;
}
.comment_box {
width: 100%;
height: 50px;
overflow: scroll;
margin-bottom: 5px;
}
.comment {
display: flex;
justify-content: space-between;
height: 25px;
}
.comment i {
margin: 5px 0;
}
.comment .fa-times {
margin-right: 5px;
}
.comment_box::-webkit-scrollbar {
display: none;
}
.comment_input_box {
width: 615px;
height: 65px;
padding: 0 25px;
display: flex;
justify-content: space-between;
}
.comment_enter {
color: #C1E0FD;
margin: auto 0;
}
.comment_enter:hover {
cursor: pointer
}
.comment_input {
width: 520px;
background-color: white;
margin: auto 0;
color: gray ;
border: white;
height: 20px;
border-radius: 3px;
}
.main_right {
display: flex;
flex-direction: column;
width: 325px;
position: fixed;
top: 100px;
}
.my_profile {
display: flex;
flex-direction: row;
margin-bottom: 20px;
width: 325px;
margin-left: 20px;
}
.my_photo img {
width: 55px;
height: 55px;
border-radius: 50%;
}
.my_info {
padding: 10px;
}
.my_name {
color: #8E8E8E;
}
.story {
width: 100%;
height: 250px;
padding: 20px;
border: rgb(219, 219, 219) 1px solid;
border-radius: 3px;
margin-bottom: 20px;
display: flex;
flex-direction: column;
background-color: white;
overflow: scroll;
}
.story::-webkit-scrollbar {
display: none;
}
.story_nav {
color: gray;
margin-bottom: 5px;
display: flex;
justify-content: space-between;
}
.story_peeds {
display: flex;
flex-direction: column;
}
.user_photo {
width: 35px;
height: 35px;
border-radius: 50%;
margin-right: 10px;
}
.story_peed {
margin-bottom: 5px;
display: flex;
flex-direction:row;
}
.recommend {
height: 150px;
padding: 20px;
border: 1px rgb(219, 219, 219) solid;
background-color: white;
border-radius: 3px;
display: flex;
flex-direction: column;
overflow: scroll;
}
.recommend::-webkit-scrollbar {
display: none;
}
.recommend_peeds {
display: flex;
flex-direction: column;
}
.recommend_peed {
margin-bottom: 5px;
display: flex;
flex-direction:row;
}
.recommend_info {
display: flex;
justify-content: space-between;
}
.follow {
margin-left: 134px;
color: #0095F6;
}
.follow:hover {
cursor: pointer;
}
footer {
color: rgb(219, 219, 219);
font-size: 12px;
margin-top: 15px;
}
@media screen and (max-width: 1000px) {
.main_right {
display: none;
}
}
클론 코딩은 처음이여서 그런지 CSS를 하면서 모르는부분을 많이 배웠다.
z-index 개념은 알고있었는데 z-index가 적용이 안될때가 있다는건 처음알았다.
처음에 text-indent을 몰라서 input
태그 안에 padding을 줘서 조절했는데 그렇게 하다가 보니까 계속 망가졌는데 text-indent을 알게되서 잘 조절하였다.
값이 양수이면 들여쓰기, 값이 음수이면 내어쓰기가 된다!
스토리를 구현하다가 알게된 기능이다.
넘어간 컨텐츠는 잘리고, 스크롤바가 생겨서 스크롤해서 볼 수 있는 기능인데 가로&세로 스크롤바가 생겨서 보기가 안좋아서 이걸 어떻게 지울까 구글링하다 방법을 찾았다. 4번이 그 내용이다.
스크롤에 대한 스타일을 변경해줄수있는 기능이다.
스크롤 보기싫어서 display: none 을 줬다.
"use strict";
const $navSearch = document.querySelector('.nav_search input')
const $searchPlus = document.querySelector('.search_plus')
const $searchIcon = document.querySelector('#search_icon')
const $myProfile = document.querySelector('#my_profile')
const $myProfilePlus = document.querySelector('.my_profile_plus')
const $myProfilePlusList = document.querySelector('.my_profile_plus li')
const $love = document.querySelector('#love')
const $feedLikes = document.querySelector('.feed_likes')
const $commentBox = document.querySelector('.comment_box')
const $commentInput = document.querySelector('.comment_input')
const $comment = document.querySelector('.comment')
const $commentEnter = document.querySelector('.comment_enter')
const $keywords = ['wecode_bootcamp']
let keyword = ""
// 메뉴바 검색기능
function keywordSplit(){
for(let i = 0; $keywords.length > i; i++ ){
keyword += $keywords[i]
}
return keyword.split('')
}
const smallKeyword = keywordSplit()
$navSearch.addEventListener( 'keyup', () => {
for(let i = 0; $navSearch.value.length > i; i++){
if ($navSearch.value[i] === smallKeyword[i]){
$searchPlus.style.display = 'flex'
i= i+1
return;
}
else {
$searchPlus.style.display = 'none'
}
}
if(!$navSearch.value){
$searchPlus.style.display = 'none'
return;
}
})
// 메뉴바 검색창
$navSearch.addEventListener('focus', (event) => {
event.target.style.textIndent= '20px'
$searchIcon.style.display = 'none'
$navSearch.value=''
})
$navSearch.addEventListener('blur', (event) => {
event.target.style.textIndent = '95px'
$searchIcon.style.display = 'inline-block'
$navSearch.value = '검색'
$searchPlus.style.display = 'none'
})
//내 프로필
$myProfile.addEventListener('click',() => {
if ($myProfilePlus.style.display === 'none'){
$myProfilePlus.style.display = 'block'
if($myProfilePlus.style.display === 'block'){
document.querySelector('body').addEventListener('click',(event)=>{
if(event.target == $myProfilePlusList){
$myProfilePlus.style.display = 'none'
console.log(1)
}
})
}
}
else {
$myProfilePlus.style.display = 'none'
}
})
//댓글 입력창 (키보드입력)
$commentInput.addEventListener('keyup', (event) => {
if (event.key === 'Enter' && $commentInput.value) {
$commentBox.innerHTML += '<div class = "comment">'+'<div>' + '<b>wecode_bootcamp </b>'+ $commentInput.value + '</div>' + '<div><i class="fas fa-times"></i><i class="far fa-heart"></i></div>' + '</div>';
$commentInput.value = ''
return;
}
if ($commentInput.value) {
$commentEnter.style.color = '#0095F6'
return;
}
if (!$commentInput.value){
$commentEnter.style.color = '#C1E0FD'
return;
}
})
//댓글 입력창 (마우스클릭)
$commentEnter.addEventListener('click', () => {
if ($commentInput.value) {
$comment.innerHTML += '<div class = "comment">'+'<div>' + '<b>wecode_bootcamp </b>'+ $commentInput.value + '</div>' + '<div><i class="fas fa-times"></i><i class="far fa-heart"></i></div>' + '</div>';
$love.setAttribute('class', 'far fa-heart');
$commentInput.value = ''
}
})
//댓글 좋아요 구현
$commentBox.addEventListener('click',(event) => {
if(event.target.className === "far fa-heart" ||
event.target.className === "fas fa-heart"){
if(event.target.style.color === 'rgb(237, 73, 86)'){
event.target.style.color = 'black'
event.target.setAttribute('class', 'far fa-heart');
}
else{
event.target.style.color = 'rgb(237, 73, 86)'
event.target.setAttribute('class', 'fas fa-heart');
}
}
})
// 댓글 삭제 기능
$commentBox.addEventListener('click',(event) => {
if(event.target.className === "fas fa-times"){
event.target.parentNode.parentNode.remove();
}
})
// 피드 좋아요 구현
$love.addEventListener('click', () => {
if($love.style.color === 'rgb(237, 73, 86)'){
$love.style.color = 'black'
$love.setAttribute('class', 'far fa-heart');
$feedLikes.innerHTML = '<b>CSS</b>님 외 3명이 좋아합니다'
}
else{
$love.style.color = 'rgb(237, 73, 86)'
$love.setAttribute('class', 'fas fa-heart');
$feedLikes.innerHTML = '<b>wecode_bootcamp</b>님 외 4명이 좋아합니다'
}
})
strict 모드로 설정하는하는 건데 제일 상단에 "use strict"를 추가해주면 된다.
strict 모드에서 허용되지 않은 문법
- 정의되지 않은 변수의 사용
- 변수나 객체의 삭제
- 함수 파라미터에 중복된 이름
- 8진수
- 이스케이프 문자
- 읽기전용 프로퍼티에 값 설정
- 조회 전용 프로퍼티에 값 설정
- eval, arguments 문자열에 대한 변수로의 사용
- with 사용
- eval() 에 정의된 변수 사용
엘리먼트가 focus를 잃었을 때 발생되는 이벤트인데
같은 용도로 사용되는 이벤트로 focusout가 있다.
둘의 차이점은 버블링의 차이인데
focusout는 버블링이 일어나고, blur는 버블링이 일어나지 않는다.
버블링에 관한 영상을 본 적 있는데 다시 한번 봐야 할 거 같다.
우측 상단에 사용자 메뉴가 있다.
저걸 누르면 실제 인스타그램 처럼 정보가 나오는데 다른곳을 클릭하면 없어지지않는다.
$myProfile.addEventListener('click',() => {
if ($myProfilePlus.style.display === 'none'){
$myProfilePlus.style.display = 'block'
if($myProfilePlus.style.display === 'block'){
document.querySelector('body').addEventListener('click',(event)=>{
if(event.target == $myProfilePlusList){
$myProfilePlus.style.display = 'none'
}
})
}
}
else {
$myProfilePlus.style.display = 'none'
}
})
이 부분인데 이미지에 focus 이벤트를 줄 수 없다고 한다.
부여하고 싶다면 img
태그에 tabindex 속성을 주면 된다고 하는데 안된다. 어떤 분은 buttom
태그를 감싸면 된다고 하는데 안된다.
굳이 이 방법 말고도 더욱 효율성 좋은 방법들이 많겠지만 이게 왜 안되는지 알고 싶다 😩
console.log(1)을 해봤는데 누르면 누를수록 1이 많이 찍힌다.(이게 버블링인가?)
참고사이트
https://uwostudy.tistory.com/55
https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=anonymousx&logNo=10183869727
https://mygumi.tistory.com/321