노트
HTML
<div class="note"> <p> 오늘도 또 우리 수탉이 막 쫓기었다. 내가 점심을 먹고 나무를 하러 갈 양으로 나올 때이었다. 산으로 올라서려니까 등뒤에서 푸르득푸드득, 하고 닭의 횃소리가 야단이다. 깜짝 놀라서 고개를 돌려보니 아니나다르랴, 두 놈이 또 얼리었다. </p> <p> 점순네 수탉(은 대강이가 크고 똑 오소리같이 실팍하게 생긴 놈)이 덩저리 작은 우리 수탉을 함부로 해내는 것이다. 그것도 그냥 해내는 것이 아니라 푸드득 하고 면두를 쪼고 물러섰다가 좀 사이를 두고 또 푸드득 하고 모가지를 쪼았다. 이렇게 멋을 부려 가며 여지없이닦아 놓는다. 그러면 이 못생긴 것은 쪼일 적마다 주둥이로 땅을 받으며 그 비명이 킥, 킥할 뿐이다. 물론 미처 아물지도 않은 면두를 또 쪼이어 붉은 선혈은 뚝뚝 떨어진다. </p> <img src="https://i.imgur.com/pEmnc36.jpg" alt="roster" /> <p> 이걸 가만히 내려다보자니 내 대강이가 터져서 피가 흐르는 것같이 두 눈에서 불이 번쩍난다. 대뜸 지게 막대기를 메고 달려들어 점순네 닭을 후려칠까 하다가 생각을 고쳐먹고헛매질로 떼어만 놓았다. </p> <p> 이번에도 점순이가 쌈을 붙여 놨을 것이다. 바짝바짝 내 기를 올리느라고 그랬음에 틀림없을 것이다. </p> <p> 고놈의 계집애가 요새로 들어서서 왜 나를 못 먹겠다고 고렇게 아르렁거리는지 모른다. </p> <p>나흘 전 감자 조각만 하더라도 나는 저에게 조금도 잘못한 것은 없다.</p></div>
.note
를 생성하고 아래에 텍스트와 이미지를 추가했습니다.
외에도 다양한 요소를 추가하실 수 있지만, 높이나 너비를 잘 고려하셔야 합니다.
CSS
:root { --bg-color: #fff; --bg-transparent: rgba(255, 255, 255, 0); --border-color: #2035a7;}
.note { font-size: 16px; line-height: 32px; border: 2px solid var(--border-color); background: -webkit-linear-gradient( top, var(--border-color) 0%, var(--border-color) 1px, var(--bg-transparent) 1px, var(--bg-transparent) 100% ); background: linear-gradient( to bottom, var(--border-color) 0%, var(--border-color) 1px, var(--bg-transparent) 1px, var(--bg-transparent) 100% ); background-size: 100% 32px;}
.note > p { margin: 0; padding: 0 4px;}
.note > img { display: block; width: auto; max-width: 100%; margin: 0 auto; object-fit: cover;}
노트 제작은 굉장히 간단한 편입니다.
1px짜리 줄 하나 긋는 그래디언트를 만든 뒤, 32px마다 반복되게 해뒀습니다.
아래에 들어갈 요소들의 높이만 전부 신경 써준다면 노트에 쓰는 느낌으로 글을 쓸 수 있습니다.
JS
function resizeImageForNote() { const note = document.querySelectorAll(".note"); const resize = () => note.forEach(resizeImage);
resize(); window.addEventListener("load", resize, { passive: true }); window.addEventListener("resize", resize, { passive: true });}
function resizeImage(element) { element.querySelectorAll("img").forEach((img) => { const { naturalWidth, naturalHeight } = img; const ratio = naturalHeight / naturalWidth; const newHeight = element.offsetWidth * ratio;
img.height = Math.floor(newHeight - (newHeight % 32)); });}
resizeImageForNote();
이미지처럼 일정 비를 유지하며 작아져야 하는 요소를 위한 예제입니다.
CSS에서 줄 간격을 변경하시면 newHeight % 32
의 32도 그 값으로 변경해주셔야 합니다.
결과
원고지
HTML
<div class="manuscript-container"> <div class="manuscript"> <p> 오늘도 또 우리 수탉이 막 쫓기었다. 내가 점심을 먹고 나무를 하러 갈 양으로 나올 때이었다. 산으로 올라서려니까 등뒤에서 푸르득푸드득, 하고 닭의 횃소리가 야단이다. 깜짝 놀라서 고개를 돌려보니 아니나다르랴, 두 놈이 또 얼리었다. </p> <p> 점순네 수탉(은 대강이가 크고 똑 오소리같이 실팍하게 생긴 놈)이 덩저리 작은 우리 수탉을 함부로 해내는 것이다. 그것도 그냥 해내는 것이 아니라 푸드득 하고 면두를 쪼고 물러섰다가 좀 사이를 두고 또 푸드득 하고 모가지를 쪼았다. 이렇게 멋을 부려 가며 여지없이닦아 놓는다. 그러면 이 못생긴 것은 쪼일 적마다 주둥이로 땅을 받으며 그 비명이 킥, 킥할 뿐이다. 물론 미처 아물지도 않은 면두를 또 쪼이어 붉은 선혈은 뚝뚝 떨어진다. </p> <img src="https://i.imgur.com/pEmnc36.jpg" alt="roster" /> <p> 이걸 가만히 내려다보자니 내 대강이가 터져서 피가 흐르는 것같이 두 눈에서 불이 번쩍난다. 대뜸 지게 막대기를 메고 달려들어 점순네 닭을 후려칠까 하다가 생각을 고쳐먹고헛매질로 떼어만 놓았다. </p> <p> 이번에도 점순이가 쌈을 붙여 놨을 것이다. 바짝바짝 내 기를 올리느라고 그랬음에 틀림없을 것이다. </p> <p> 고놈의 계집애가 요새로 들어서서 왜 나를 못 먹겠다고 고렇게 아르렁거리는지 모른다. </p> <p>나흘 전 감자 조각만 하더라도 나는 저에게 조금도 잘못한 것은 없다.</p> </div></div>
.note
와 마찬가지지만 줄 공책과 달리 원고는 한 칸의 크기가 정해져 있어 .manuscript
의 크기도 유동적으로 변경되어야 하기에, .manuscript
를 감싸주는 .manuscript-container
가 하나 추가되었습니다.
CSS
:root { --bg-color: #fff; --bg-transparent: rgba(255, 255, 255, 0); --border-color: #d12e2e;}
.manuscript-container { margin: 0 auto;}
.manuscript { font-size: 16px; line-height: 32px; padding: 8px 0; border: 2px solid var(--border-color); background: -webkit-linear-gradient( top, var(--bg-transparent) 0%, var(--bg-transparent) 1px, var(--bg-color) 1px, var(--bg-color) 8px, var(--bg-transparent) 8px, var(--bg-transparent) 100% ), -webkit-linear-gradient( top, var(--bg-transparent) 0%, var(--bg-transparent) 1px, var(--bg-color) 1px, var(--bg-color) 8px, var(--bg-transparent) 8px, var(--bg-transparent) 100% ), -webkit-linear-gradient( left, var(--border-color) 0%, var(--border-color) 1px, var(--bg-transparent) 1px, var(--bg-transparent) 100% ), -webkit-linear-gradient( top, var(--border-color) 0%, var(--border-color) 1px, var(--bg-transparent) 1px, var(--bg-transparent) 100% ), -webkit-linear-gradient( top, var(--border-color) 0%, var(--border-color) 1px, var(--bg-transparent) 1px, var(--bg-transparent) 100% ), var(--bg-color); background: linear-gradient( to bottom, var(--bg-transparent) 0%, var(--bg-transparent) 1px, var(--bg-color) 1px, var(--bg-color) 8px, var(--bg-transparent) 8px, var(--bg-transparent) 100% ), linear-gradient( to bottom, var(--bg-transparent) 0%, var(--bg-transparent) 1px, var(--bg-color) 1px, var(--bg-color) 8px, var(--bg-transparent) 8px, var(--bg-transparent) 100% ), linear-gradient( to right, var(--border-color) 0%, var(--border-color) 1px, var(--bg-transparent) 1px, var(--bg-transparent) 100% ), linear-gradient( to bottom, var(--border-color) 0%, var(--border-color) 1px, var(--bg-transparent) 1px, var(--bg-transparent) 100% ), linear-gradient( to bottom, var(--border-color) 0%, var(--border-color) 1px, var(--bg-transparent) 1px, var(--bg-transparent) 100% ), var(--bg-color); background-size: 24px 32px; margin: 0 auto; background-position: 0 -1px, 0 0, -1px 0, 0 8px, 0px -1px;}
.manuscript > p { display: flex; flex-wrap: wrap; margin: -8px -1px 8px 0; font-size: 16px; line-height: 24px;}
.manuscript > p > span { display: inline-block; text-align: center; width: 24px; height: 24px; flex-shrink: 0; margin-top: 8px;}
.manuscript > :empty:not(img) { height: 32px; margin-bottom: 8px;}
.manuscript > :last-child { margin-bottom: 0;}
.manuscript > img { display: block; width: auto; max-width: 100%; margin: 0 auto; object-fit: cover;}
.manuscript > *:not(:last-child) { margin-bottom: 40px;}
그래디언트도 조금 골이 아파지기 시작합니다.
원고 한 칸의 크기를 24px * 24px, 줄 간격을 8px로 잡고 만들었으니, 수정하실 때 참고해주세요.
JS
function initManuscript() { const manuscript = document.querySelectorAll(".manuscript"); const handleResize = () => { manuscript.forEach((elt) => { resizeMnuascriptContainer(elt); resizeImage(elt); }); };
window.addEventListener("load", handleResize, { passive: true }); window.addEventListener("resize", handleResize, { passive: true });
manuscript.forEach((element) => { element.querySelectorAll("p").forEach((element) => { const text = element.innerText;
element.innerHTML = ""; [...text].forEach((word) => { const span = document.createElement("span"); const textNode = document.createTextNode(word);
span.appendChild(textNode); element.append(span); }); }); });
handleResize();}
function resizeMnuascriptContainer(element) { element.style.width = `${ (Math.floor(element.parentElement.offsetWidth / 24) - 1) * 24 - 1 }px`;}
function resizeImage(element) { element.querySelectorAll("img").forEach((img) => { const { naturalWidth, naturalHeight } = img; const ratio = naturalHeight / naturalWidth; const newHeight = element.offsetWidth * ratio;
img.height = Math.floor(newHeight - (newHeight % 32) - 8); });}
initManuscript();
노트와 마찬가지로 이미지의 크기를 유동적으로 변경해주는 스크립트에 최초에 글자를 하나하나 뜯어서 span
에 넣어주는 스크립트와, 원고지의 크기를 유동적으로 변경해주는 스크립트가 추가되었습니다.
원고 칸의 크기를 수정하시면 resizeManuscriptContainer
, resizeImage
에 들어있는 8의 배수(8, 24, 32)들을 모조리 수정해주시면 됩니다.
결과
여담
아무래도 노트와 달리 한 칸에 맞춰서 글자를 써야 하다 보니 글자를 모조리 span
에 담아야 깔끔하게 작업할 수 있었습니다.
이 때문에 검색 엔진이 본문의 내용을 파악하기 힘들어질 수 있고, SEO에 악영향을 미칠 수 있습니다.
해당 스크립트가 SEO에 미치는 영향 등은 조사해보지 않았으니 이 점 유의해주세요.