css
.tag {
display: inline-block;
background: cornsilk;
padding: 16px;
font-size: 30px;
border: 10px solid coral;
/* height: 100px;
overflow-y: auto; */
}
span { font-size: 16px; }
.box {
position: absolute;
top: 500px;
left: 200px;
width: 400px;
height: 200px;
background: lightblue;
}
html
<div class="tag">윈도우 사이즈</div>
<div class="box">박스 사이즈</div>
js
const tag = document.querySelector(".tag");
const box = document.querySelector(".box");
const rect = box.getBoundingClientRect();
console.log(rect);
function updateTag() {
tag.innerHTML = `
window.screen : ${window.screen.width}, ${window.screen.height}
<span> - 스크린(모니터) 가로길이. 변하지 않음</span> <br>
window.outer : ${window.outerWidth}, ${window.outerHeight}
<span> - 브라우저 (주소창, 탭, 스크롤바 포함⭕) 가로, 세로 길이</span> <br>
window.inner : ${window.innerWidth}, ${window.innerHeight}
<span> - 브라우저 (주소창, 탭, 스크롤바 포함❌) 가로, 세로 길이</span> <br>
document.client : ${document.documentElement.clientWidth}, ${document.documentElement.clientHeight}
<span> - border의 안쪽만, background가 작동되는 영역</span> <br><br>
.tag의 넓이 (clientWidth) : ${tag.clientWidth}, ${tag.clientHeight}
<span> - padding 포함⭕, border 포함❌, 스크롤바 포함❌</span> <br>
.tag의 넓이 (offsetWidth) : ${tag.offsetWidth}, ${tag.offsetHeight}
<span> - padding 포함⭕, border 포함⭕</span> <br>
`;
}
function boxSize() {
box.innerHTML = `
<strong>Element.getBoundingClientRect() </strong><br>-엘리먼트의 크기, 뷰포트에 상대적인 위치 정보를 제공하는 매서드<br><br>
${rect.bottom} - 화면 위에서 부터 박스 아래쪽까지의 거리<br>
${rect.right} - 화면 왼쪽에서 부터 박스 오른쪽까지의 거리<br>
${rect.x} ,${rect.y} - 좌표
${rect.width} ,${rect.height} - 가로넓이, 세로넓이(border도 포함)
`;
}
window.addEventListener("resize", () => {
updateTag(); // resize 이벤트 발생될 때 함수 실행
});
updateTag();
boxSize();
css
/* basic.css */
@charset "UTF-8";
* { box-sizing: border-box; }
body {
font-family: Verdana, Geneva, Tahoma, sans-serif; background: cornsilk;
margin: 50px;
}
button {
outline: 0;
border: 0;
background: transparent;
cursor: pointer;
}
section {
min-width: 360px;
max-width: 600px;
margin: auto;
background: #f1f7ff;
border-radius: 15px;
box-shadow: 5px 5px 10px rgba(0, 0, 0, 15%);
}
header {
height: 48px;
line-height: 48px;
background: rgb(180,205,255);
background: linear-gradient(45deg, rgba(180,205,255,1) 0%, rgba(233,179,255,1) 100%);
border-radius: 15px 15px 0 0;
text-align: center;
color: #fff;
}
ul.items {
height: 500px;
overflow-y: auto;
padding-bottom: 30px;
}
.item_row {}
.item {
display: flex;
justify-content: space-between;
align-items: center;
height: auto;
padding: 10px 32px;
}
.item_name {}
.itemDelete_btn {
font-size: 18px;
transition: .2s ease-in;
}
.itemDelete_btn:hover { color: red; transform: scale(1.1); }
.item_divider {
width: 90%;
height: 1px;
margin: auto;
background-color: #d7c8ff;
}
footer {
background: rgb(180,205,255);
background: linear-gradient(45deg, rgba(180,205,255,1) 0%, rgba(233,179,255,1) 100%);
border-radius: 0 0 15px 15px;
text-align: center;
}
.f_input {
width: 100%;
height: 40px;
padding: 0 32px;
border: 0;
outline: none;
font-size: 18px;
}
.f_input::placeholder { color: #ddd; }
.f_addBtn {
width: 48px;
height: 48px;
font-size: 25px;
color: rgba(255, 255, 255, .5);
transition: .3s ease-in;
}
.f_addBtn:hover { color: rgba(255, 255, 255, 1); transform: scale(1.1); }
html
<section>
<header>ShoppingList</header>
<ul class="items">
<li class="item_row">
<div class="item">
<span class="item_name">아이스크림</span>
<button class="itemDelete_btn">
<i class="fa-solid fa-trash-can"></i>
</button>
</div>
<div class="item_divider"></div>
</li>
<li class="item_row">
<div class="item">
<span class="item_name">아이스크림2</span>
<button class="itemDelete_btn">
<i class="fa-solid fa-trash-can"></i>
</button>
</div>
<div class="item_divider"></div>
</li>
</ul>
<footer>
<input type="text" class="f_input" placeholder="enter your shopping list">
<button class="f_addBtn">
<i class="fa-solid fa-circle-plus"></i>
</button>
</footer>
</section>
js
const items = document.querySelector(".items"); // ul
const input = document.querySelector(".f_input");
const addBtn = document.querySelector(".f_addBtn");
// *클릭하면 발생할 함수 정의
function onAdd() {
// 1. input 입력값 가져오기 (비어있지 않을 때)
const text = input.value;
if (text == "") {
input.focus();
return;
}
// 2. 새로운 아이템을 만듦 (li.item_row)
const item = createItem(text); // 리턴된 입력값 받아옴
// 3. ul.items에 만든 아이템 추가
items.append(item);
// 4. 새로 추가된 아이템 부분이 화면에 보이게(스크롤되게)
item.scrollIntoView();
// 5. input 초기화
input.value = "";
input.focus();
}
let id = 0;
// *li.item_row를 만드는 함수
function createItem(text) {
const itemRow = document.createElement("li");
itemRow.setAttribute("class", "item_row");
itemRow.setAttribute("data-id", id);
// data attribute : 클래스와 같은 역할을 함(사용자 지정)
// 스트링 리터럴 방식으로 추가
itemRow.innerHTML = `
<div class="item">
<span class="item_name">${text}</span>
<button class="itemDelete_btn">
<i class="fa-solid fa-trash-can" data-id = ${id}></i>
</button>
</div>
<div class="item_divider"></div>
`;
id++;
/*
const item = document.createElement("div");
item.setAttribute("class", "item");
const name = document.createElement("span");
name.setAttribute("class", "item_name");
name.innerText = text;
// 휴지통 button 추가
const deleteBtn = document.createElement("button");
deleteBtn.classList.add("itemDelete_btn");
deleteBtn.innerHTML = '<i class="fa-solid fa-trash-can"></i>';
deleteBtn.addEventListener("click", () => {
items.removeChild(itemRow);
// itemRow는 items 안에 있음
})
// *css line 추가
const itemDivider = document.createElement("div");
itemDivider.classList.add("item_divider");
// *위에서 태그를 생성 후 append로 한 단계씩 적용
// a.append() : a 맨 뒤에 내용 추가
item.append(name);
item.append(deleteBtn)
itemRow.append(item);
itemRow.append(itemDivider);
*/
return itemRow; // 최종적으로 만들어 준 itemRow를 리턴
}
addBtn.addEventListener("click", onAdd);
input.addEventListener("keypress", (event) => {
// 아래 3개 코드는 전부 같은 뜻
// if (event.key === "Enter") { onAdd(); }
// event.key === "Enter" ? onAdd() : "return";
event.key === "Enter" && onAdd(); // Enter와 onAdd만
});
input.addEventListener("focus", () => {
input.removeAttribute("placeholder");
});
// 추가) 이벤트 위임
items.addEventListener("click", (event) => {
console.log("ㅎㅇ"); // ul 안 아무 곳이나 발생
// delete 버튼을 누를 때만 반응
const idc = event.target.dataset.id;
// 쓰레기통 눌렀을 때만 id값 받아옴 (dataset 안에서만 발생)
console.log(idc);
if (idc) {
// 자식요소 삭제
// items.removeChild(itemRow);
const toBeDeleted = document.querySelector(`.item_row[data-id="${idc}"]`); // idc값을 가지고 있는 li
toBeDeleted.remove();
}
});
css
/* basic.css */
@charset "UTF-8";
body { font-family: "noto sans kr", Verdana, Geneva, Tahoma, sans-serif; }
a { color: inherit; }
header {
position: fixed;
width: 100%;
color: #fff;
z-index: 9999;
backdrop-filter: blur(5px);
transition: .3s ease-in;
}
.header_in {
max-width: 1240px;
margin: auto;
height: 120px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}
header h1 {}
header h1 i {
font-size: 2em;
color: #d9f4ff;
margin-right: 10px;
}
header h1 span {
font-size: 3em;
font-family: 'Economica', sans-serif;
font-weight: 700;
}
nav {}
nav ul {}
nav ul::after { display: block; content: ""; clear: both; }
nav li {
float: left;
}
nav li a {
padding: 10px;
font-style: 18px;
}
nav li a:hover { color: #cfcfcf; }
header.on { background: #000; }
header.on h1 i { color: rgba(255, 255, 255, .7) }
header.on nav li a:hover { color: rgba(255, 255, 255, .3) }
header.on .header_in { height: 50px; }
header.on h1 i {
font-size: 1.5em;
margin-right: 5px;
}
header.on h1 span { font-size: 1.7em; }
header.on nav li a {
padding: 10px;
font-size: 14px;
}
.visual {
width: 100%;
height: 100vh;
}
.visual > div {
width: 100%;
height: 100%;
}
.visual > div video {
/* fullpage에서 이미지나 동영상을 화면에 꽉 채우는 법 */
width: 100%;
height: 100%;
object-fit: cover;
}
section {
width: 960px;
margin: 50px auto;
}
section p {
border: 1px solid #ccc;
padding: 40px;
margin: 20px 0;
}
html
<header>
<div class="header_in">
<h1>
<i class="fa-solid fa-cloud"></i>
<span>Portfolio</span>
</h1>
<nav>
<ul>
<li><a href="#">HOME</a></li>
<li><a href="#">UI/UX</a></li>
<li><a href="#">RESPONSIVE</a></li>
<li><a href="#">REACT</a></li>
<li><a href="#">FRONT END</a></li>
<li><a href="#"></a></li>
</ul>
</nav>
</div>
</header>
<div class="visual">
<div>
<video src="./img/main.mp4" autoplay muted loop></video>
</div>
</div>
<section id="section">
<p>Aliqua officia occaecat pariatur elit officia quis aliqua cillum et culpa pariatur dolore. Est et nisi irure consequat. Duis ullamco eiusmod id commodo sint est culpa labore pariatur adipisicing exercitation. Occaecat deserunt sunt eu est consectetur ullamco ut ea aliquip consectetur Lorem ea. Ipsum fugiat occaecat do dolor minim in deserunt commodo. Aute ut cupidatat velit eiusmod Lorem ad duis ut aliquip est proident. Ad incididunt amet aliquip excepteur culpa nulla tempor fugiat reprehenderit exercitation do sint. Excepteur velit sint et culpa ea deserunt nostrud excepteur. Eiusmod laboris deserunt eiusmod id irure. Dolore incididunt eiusmod anim sint. Commodo laborum labore laborum ullamco nostrud dolor.</p>
<!-- 코드가 너무 길어져서 아래쪽 p 태그는 생략 -->
</section>
js
// jQuery - 스크롤 되면 무조건 실행
$(window).scroll(function () {
$("header").addClass("on");
if ($(window).scrollTop() == 0) {
$("header").removeClass("on");
}
});
// $(window).scrollTop() - 화면 스크롤이 얼마나 되었는지 반환(메소드, 프로퍼티)
// javascript
const header = document.querySelector("header");
// js - 스크롤 되면 무조건 실행
const header = document.querySelector("header");
window.addEventListener("scroll", () => {
header.classList.add("on");
if (window.scrollY == 0) {
header.classList.remove("on");
}
});
// js - 300만큼 스크롤이 되면 실행
window.addEventListener("scroll", () => {
if (window.scrollY > 300) {
header.classList.add("on");
} else {
header.classList.remove("on");
}
});
// js - 동영상에서(fullpage) 벗어나는 순간 실행
window.addEventListener("scroll", () => {
if (window.scrollY > section.offsetTop) { // id="section"이 있는 곳에서 바뀜
header.classList.add("on");
} else {
header.classList.remove("on");
}
});
동영상에서(fullpage) 벗어나는 순간 실행
header에 backdrop-filter 적용되어 있음
아직 동영상 내부에 있어서 header에 변화 없음
동영상을 벗어나니 header에 js가 적용되는 모습