
현재 내 티스토리는 hELLO 스킨을 사용하고 있다.
기본도 심플하고 예쁘지만 hELLO 스킨 기반으로 커스텀한 다른 블로그들 보면서 너무 예쁘다고 생각했다..!!
나도 나중에 수정해야지~ 생각만 하고 귀찮아서 안 했는데 ㅎ
이번에 하나하나씩 수정해보려고 한다.
블로그 관리 > 스킨 편집 > html 편집으로 이동해서 스킨을 커스텀할 수 있다.
아 그리고 혹시 플러그인 중에 코드 문법 강조를 적용하고 있다면 해제해야 한다.
아무것도 안건들였을 때에도 다크모드를 하면 코드블록 글씨 색상이 이상했는데 이 플러그인 때문이었다.

✏️ 폰트 설정
웹 폰트를 활용해서 코드 블록의 폰트를 변경하려고 한다.
먼저 원하는 폰트를 찾아둔다.
나는 D2Coding 폰트로 바꾸기 위해 눈누에서 웹폰트를 복사했다.

복사한 내용을 CSS 상단에 붙여 넣는다.

아래에서 code, kbd, samp, pre가 있는 곳을 찾아 font-family 가장 앞에 변경하려는 폰트 이름을 추가한다.
나는 D2Coding을 추가해 줬다.

적용을 눌러서 폰트가 잘 적용됐는지 확인한다.
✏️ 코드 블록 테마 설정
스킨 편집에서 가장 하단에 코드 하이라이팅이 있다.
highlight.js Demo에서 테마를 확인해 보고 원하는 테마를 선택해서 이름을 넣는다.

스킨 편집에서 가장 하단에 코드 하이라이팅이 있다.
라이트 모드와 다크모드를 따로따로 해도 되고 둘 다 한 테마를 해도 상관없다.
다만, 코드 하이라이팅(Light)에도 다크 버전의 테마를 사용하고 싶다면 코드블록의 배경색을 바꿔줘야 한다.
html 편집의 CSS 탭에서 #article .contents_style pre code.hljs를 찾아 background-color 값을 바꾼다.
원하는 색상을 지정해도 되고, 그냥 다크모드의 색상을 복사해서 라이트모드에 붙여 넣기 해도 된다.

✏️ 코드 블록 커스터마이징
아래 세 블로그의 코드를 참고했다.
첫 번째 블로그의 코드를 기반으로 두 번째 블로그와 세 번째 블로그를 참고해서 내가 원하는 대로 수정했다.
2. [hELLO 스킨] 코드 블럭의 테마, 폰트 설정 및 커스터마이징
안녕하세요, 레오입니다. 스킨을 새로운 버전으로 업데이트를 했으니, 이제부터 본격적으로 스킨을 커스터마이징 해보겠습니다. 제가 가장 먼저 수정해야겠다고 마음 먹은 부분은 개발자들이
jake8440.tistory.com
[티스토리 블로그 테마] - 1. 코드 블록 디자인을 mac 코드 스타일로 바꾸기
글을 읽기 전 미리 보는 완성본은 다음과 같다. 어떻게 만들었고 적용했는지 궁금하신 분들은 아래로 스크롤! See the Pen tistory code block by MiJeong Kim (@sap03110) on CodePen. 발단여느 날과 다름없이
guiyomi.tistory.com
[티스토리] 코드 블록 mac 스타일 적용 (feat. hELLO)
코드블록 mac 디자인 평소처럼 일을 하면서 구글링을 해서 여러 기술 블로그들을 확인하게 되는데, 거의 대부분의 블로거 분들이 티스토리 기본 코드 블록을 사용하기보다는 디자인을 커스터마
reifier.tistory.com
내가 원하는 것은 아래 항목들이었고, 이를 적용한 모습이다.
- mac 스타일 헤더 꾸미기 (높이 작게)
- 헤더에 코드 복사 버튼 넣기 (클릭 전에는 복사 아이콘, 클릭하면 잠시 체크 아이콘으로 변경)
- 줄 번호 표시하기
- hover 한 라인에 배경색 어둡게 하는 효과 주기
- 코드 블록 우측 하단에 Language 표시
- 라이트 모드, 다크 모드일 때 색상 다르게 하기
코드펜에서는 다크 모드일 때의 예시이다.
See the Pen Tistory Code Block by allkong (@allkong) on CodePen.
✏️ 코드 적용
나는 라이트 모드, 다크 모드를 모두 지원하는 버전으로 적용하려고 한다.
만약 라이트 모드/다크 모드 상관없이 다크 버전으로만 적용하고 싶으면 위에 올린 코드펜에서 css 참고하면 된다.
1. CSS 수정
아래 CSS를 복사해서 스킨 편집 > CSS에 붙여 넣기 한다.
다운로드하지 않고 아래 코드를 복사해도 된다.
pre {
  position: relative;
}
/* 코드 블록 언어 */
pre::after {
  content: attr(data-ke-language);
  position: absolute;
  bottom: 40px;
  right: 12px;
  color: #525353;
  font-size: 14px;
}
.dark pre::after {
  color: #cfd2d1;
}
.hljs {
  display: flex !important;
  flex-direction: column;
  padding: 0 !important;
  font-size: 14px;
  border-radius: 8px;
  font-family: D2Coding, Menlo, Courier, monospace;
}
/* 줄 번호 */
.hljs .line {
  counter-increment: line-idx;
  line-height: 1.5;
  white-space: pre;
}
.hljs .line::before {
  content: counter(line-idx);
  display: inline-block;
  width: 24px;
  margin-right: 16px;
  text-align: right;
  font-size: 0.8rem;
  color: #747a7a;
}
/* 마우스 hover 시 하이라이트 */
.hljs .line:hover {
  --tw-bg-opacity: 1;
  background-color: rgb(230 230 233 / var(--tw-bg-opacity));
}
.dark .hljs .line:hover {
  --tw-bg-opacity: 1;
  background-color: rgb(53 54 56 / var(--tw-bg-opacity));
}
/* mac 스타일 헤더 */
.hljs .code-header {
  display: flex;
  align-items: center;
  padding: 5px;
  background-color: #dadada;
  border-radius: 8px 8px 0 0;
}
.dark .hljs .code-header {
  background-color: #404043;
}
.hljs .code-header .btn {
  width: 12px;
  height: 12px;
  margin: 0 5px;
  border-radius: 50%;
}
.hljs .code-header .btn.red {
  background-color: #f5655b;
}
.hljs .code-header .btn.yellow {
  background-color: #f6bd3b;
}
.hljs .code-header .btn.green {
  background-color: #43c645;
}
.hljs .code-body {
  max-height: 600px;
  margin: 8px;
  margin-bottom: 32px;
  overflow: auto;
}
.hljs .code-body::-webkit-scrollbar {
  width: 4px;
  height: 4px;
}
.hljs .code-body::-webkit-scrollbar-thumb {
  border-radius: 4px;
  background-color: #dad9da;
}
.dark .hljs .code-body::-webkit-scrollbar-thumb {
  background-color: #4d4a4b;
}
.hljs .code-body::-webkit-scrollbar-corner {
  display: none;
}
.hljs .copy-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: auto;
  padding: 0px 12px;
  height: 32px;
  font-weight: normal;
  background-color: #00000017;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: 0.3s background-color;
}
.dark .hljs .copy-btn {
  background-color: #ffffff17;
}
.hljs .copy-btn:hover {
  background-color: #00000030;
}
.dark .hljs .copy-btn:hover {
  background-color: #ffffff30;
}
2. JavaScript 파일 업로드
아래 codeblock.js 파일을 다운로드하여서 업로드한다.
같은 내용을 코드로도 첨부한다.
const COPY_TEXT_CHANGE_OFFSET = 1000;
const COPY_ERROR_MESSAGE = "코드를 복사할 수 없습니다. 다시 시도해 주세요.";
const COPY_ICON = `
  <svg width="14" height="14" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M11.5 0.125H3.5C3.40054 0.125 3.30516 0.164509 3.23484 0.234835C3.16451 0.305161 3.125 0.400544 3.125 0.5V3.125H0.5C0.400544 3.125 0.305161 3.16451 0.234835 3.23484C0.164509 3.30516 0.125 3.40054 0.125 3.5V11.5C0.125 11.5995 0.164509 11.6948 0.234835 11.7652C0.305161 11.8355 0.400544 11.875 0.5 11.875H8.5C8.59946 11.875 8.69484 11.8355 8.76517 11.7652C8.83549 11.6948 8.875 11.5995 8.875 11.5V8.875H11.5C11.5995 8.875 11.6948 8.83549 11.7652 8.76517C11.8355 8.69484 11.875 8.59946 11.875 8.5V0.5C11.875 0.400544 11.8355 0.305161 11.7652 0.234835C11.6948 0.164509 11.5995 0.125 11.5 0.125ZM8.125 11.125H0.875V3.875H8.125V11.125ZM11.125 8.125H8.875V3.5C8.875 3.40054 8.83549 3.30516 8.76517 3.23484C8.69484 3.16451 8.59946 3.125 8.5 3.125H3.875V0.875H11.125V8.125Z" fill="currentColor"/>
  </svg>`;
const CHECK_ICON = `
  <svg width="14" height="14" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path fill-rule="evenodd" clip-rule="evenodd" d="M4.47581 9.97581C4.4101 9.97593 4.34502 9.96309 4.28428 9.93804C4.22354 9.91299 4.16833 9.87621 4.12181 9.82981L0.121809 5.82981C0.0390555 5.73383 -0.00433599 5.61011 0.00034252 5.48347C0.00502103 5.35683 0.0574233 5.23664 0.147033 5.14703C0.236642 5.05742 0.356827 5.00502 0.483467 5.00034C0.610108 4.99566 0.733832 5.03906 0.829809 5.12181L4.47581 8.76881L11.1218 2.12181C11.2178 2.03906 11.3415 1.99566 11.4682 2.00034C11.5948 2.00502 11.715 2.05742 11.8046 2.14703C11.8942 2.23664 11.9466 2.35683 11.9513 2.48347C11.956 2.61011 11.9126 2.73383 11.8298 2.82981L4.82981 9.82981C4.78329 9.87621 4.72808 9.91299 4.66734 9.93804C4.6066 9.96309 4.54151 9.97593 4.47581 9.97581Z" fill="currentColor"/>
  </svg>
`;
const func = () => {
  const codeBlocks = document.querySelectorAll("pre > code");
  // 복사
  const copyBlockCode = async (target) => {
    if (!target) return;
    try {
      const code = decodeURI(target.dataset.code);
      await navigator.clipboard.writeText(code);
      target.innerHTML = CHECK_ICON;
      setTimeout(() => {
        target.innerHTML = COPY_ICON;
      }, COPY_TEXT_CHANGE_OFFSET);
    } catch (error) {
      alert(COPY_ERROR_MESSAGE);
      console.error(error);
    }
  };
  // 코드 블럭 생성 및 복사 버튼 삽입
  for (const codeBlock of codeBlocks) {
    const codes = codeBlock.innerHTML.match(/(.*)(\n|.*$)/g).filter(Boolean);
    const processedCodes = codes.reduce(
      (prev, cur) => prev + `<div class="line">${cur}</div>`,
      ""
    );
    const copyButtonHTML = `<button type="button" class="copy-btn" data-code="${encodeURI(
      codeBlock.textContent
    )}">${COPY_ICON}</button>`;
    const codeBody = `<div class="code-body">${processedCodes}</div>`;
    const codeHeader = `
    <div class="code-header">
      <span class="red btn"></span>
      <span class="yellow btn"></span>
      <span class="green btn"></span>
      ${copyButtonHTML}
    </div>`;
    codeBlock.innerHTML = codeHeader + codeBody;
  }
  // 복사 버튼에 이벤트 리스너 연결
  const copyButtons = document.querySelectorAll(".copy-btn");
  copyButtons.forEach((button) => {
    button.addEventListener("click", () => copyBlockCode(button));
  });
};
// 랜더링 전 자바스크립트 실행을 막기 위함
window.addEventListener("load", () => {
  func();
});
파일 업로드를 하면 이렇게 된다.

3. HTML에 JavaScript 파일 연결
<script defer src="./images/codeblock.js"></script>위 코드를 HTML의 head 태그 안 마지막에 붙여 넣는다.

이제 적용을 눌러서 코드 블록이 잘 뜨는지 확인해 보면 된다.
라이트 모드, 다크 모드 모두 잘 뜬다!

