스킨 사용중에 아래의 문제를 발견했다
발견한 문제들
- 다크모드에서 코드블럭 내 복붙한 글에 다크모드 적용 안됨 (글자가 어두워 안보임)
- 다크모드에서 텍스트 에디터에 복붙한 글에 다크모드 적용 안됨 (배경 흰색, 글자 검정 유지됨)
- 다크모드에서 밝은색 하이라이트를 사용하면 흰색으로 변한 글자가 잘 안 보임
원인 분석
원인을 알면 해결책은 간단하다 .
처음에는 hljs라는 스타일이 적용되고 있는 걸 보고 스킨 css 적용 순서 문제이거나 css 상속 문제인가 싶어 찾아봤는데 그건 아니었다. 그러면 다크모드 토글여부를 mutationObserver로 관찰해서 변하는 값에 따라 css를 적용해줘야 하나 고민했지만, 너무 복잡하게 푸는 느낌이 들어서 다른 기본 요소들을 다시 짚어보았다.
복붙할 때 HTML이 어떻게 정보를 가져오는지, 여러 css가 있을 때 우선순위가 어떻게 정해지는지를 생각하니 원인이 보였다.
1. 티스토리 에디터가 복붙한 내용에 대해 자동 CSS를 적용하는 경우
2. 복붙한 내용에 글자색 및 배경색의 인라인 스타일이 적용되어있는 경우
3. 다크모드에 대한 적절한 하이라이트 색 변화가 없음
즉, 이미 스킨 css가 적용됐는데 인라인 스타일이 위에 덮어씌워진다는 생각이 들었다. 실제로 css들을 지워보니 원래의 스타일들이 잘 드러났다. CSS 우선순위 최상인 인라인 스타일이 스킨 css 위에 덮어씌워진 것이다.
그래서 jQuery로 인라인 스타일을 없애주면, 최상위 우선순위로 덮어씌워진 css 값이 사라지고 스킨 개발자님이 의도한 css가 제대로 적용된다.
해결 방법
하지만 단순히 모든 인라인 스타일을 없애는 건, 유지해야 하는 인라인 스타일(예를 들어 하이라이트)도 있어서 조금 더 보수적인 방법을 고민했다.
1,2번 해결 (다크모드에서 텍스트가 어둡게 유지되거나 일부 텍스트 배경색이 흰색으로 보이는 문제)
[다크모드에서 텍스트가 어둡게 유지되는 문제]
-> 티스토리 에디터가 복붙한 내용에 대해 자동 CSS를 적용하는 것을 없애줘서 해결
복붙할 때 span이나 div 태그가 생성되면서 인라인 스타일(data-ke-size)이 함께 적용되는 규칙이 있었는데, 이 부분을 jQuery로 없애주는 방법으로 문제를 해결했다.
이렇게 하면 복붙에 의해 만들어진, 최상위 위선순위로 작동하는 인라인 css 값이 사라지며 스킨 개발자님이 의도한 css가 드러난다.
추가로 더보기 영역에서 배경색이 흰색으로 남아있는 문제가 있어서 함께 처리해줬다.
이 블로그를 보고 코드를 몇 줄 더 추가해보았다 https://soobysu.tistory.com/137
복붙한 글자, 코드블럭(<pre><code></code></pre>로 감싸진 영역) 에서 티스토리에 의해 자동 적용된 배경색과 폰트 색상 css를 제거하고 부모 요소의 css를 상속받게 했다. (가장 가까운 부모, 혹은 가장 늦게 로드된 부모의 css 값이 적용된다)
<!-- jQuery 라이브러리 추가 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// 티스토리 에디터가 추가한 인라인 속성 및 스타일 제거
$('h1, h2, h3, h4, p, span').removeAttr('data-ke-size').css('color', '');
//코드블럭 모서리 흰색 배경 남은 것 제거
$('[data-ke-type="codeblock"]').css('background-color', '');
//코드블럭 다크모드에서 글자 색상 씹힘 이슈 해결
$('pre').removeAttr('data-ke-size').css('color', '');
$('code').removeAttr('data-ke-size').css('color', '');
$('code').css('color', 'inherit');
// 더보기 영역 배경색 초기화
$('[data-ke-type="moreLess"]').css('background-color', '');
// .moreless-content 영역에 padding 5px 적용
$('.moreless-content').css('padding', '5px');
});
</script>
[텍스트 배경색이 흰색, 글자는 검정색으로 유지되는 문제]
-> 복붙한 내용에 글자색 및 배경색의 인라인 스타일이 적용되어있는 것을 없애줘서 해결
// 인라인 style이 있는 div만 골라서 처리
$('div[style], div ul[style]').each(function() {
var styleAttr = $(this).attr('style');
if (styleAttr) {
// 정규식을 사용하여 background-color와 color 속성만 찾아 제거
var newStyle = styleAttr
.replace(/background-color\s*:\s*[^;]+;?/gi, '')
.replace(/color\s*:\s*[^;]+;?/gi, '');
// 불필요한 공백/세미콜론 정리
newStyle = newStyle.trim().replace(/;$/, '');
// style 속성을 새로 설정
$(this).attr('style', newStyle);
}
});
3번 해결 (다크모드에서 밝은 하이라이트 색과 글자색의 색상 차이가 적어 글자가 잘 안보이는 문제)
-> 밝은 하이라이트 내부 글자 색을 검정으로 바꿔줘서 해결
하이라이트는 span 태그로 묶여 인라인 스타일로 지정되는 규칙이 있다. 그래서 span 태그 중 배경색(=하이라이트 색상)의 rgb값이 특정 범위 이상이면 밝은 값이라고 여기고 글자를 검정색으로 바꿔주는 식으로 문제를 해결했다.
// background-color 속성이 포함된 span 요소만 선택
$('span[style*="background-color"]').each(function() {
// 실제로 적용된 CSS 배경색(ex. rgb(246, 225, 153)) 가져오기
var bgColor = $(this).css('background-color');
// rgb(...) 또는 rgba(...)에서 숫자만 추출하는 정규식
var matched = bgColor.match(/\d+/g);
if (matched) {
var r = parseInt(matched[0], 10);
var g = parseInt(matched[1], 10);
var b = parseInt(matched[2], 10);
// 밝기 계산 (가중치 사용)
var brightness = 0.299*r + 0.587*g + 0.114*b;
// 밝기에 따라 글자색 설정
if (brightness < 128) {
// 어두운 배경 -> 흰색 폰트
$(this).css('color', '#ffffff');
} else {
// 밝은 배경 -> 검정 폰트
$(this).css('color', '#000000');
}
}
});
전체 코드
이제 아래 코드를 ' 티스토리 스킨 편집 → HTML 편집 ' 에서 헤더에 붙여넣으면 문제가 해결된다!
<!-- jQuery 라이브러리 추가 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
// 티스토리 에디터가 추가한 인라인 속성 및 스타일 제거
$('h1, h2, h3, h4, p, span').removeAttr('data-ke-size').css('color', '');
//코드블럭 모서리 흰색 배경 남은 것 제거
$('[data-ke-type="codeblock"]').css('background-color', '');
//코드블럭 다크모드에서 글자 색상 씹힘 이슈 해결
$('pre').removeAttr('data-ke-size').css('color', '');
$('code').removeAttr('data-ke-size').css('color', '');
$('code').css('color', 'inherit');
// 더보기 영역 배경색 초기화
$('[data-ke-type="moreLess"]').css('background-color', '');
// .moreless-content 영역에 padding 13px 적용
$('.moreless-content').css('padding', '5px');
// 인라인 style이 있는 div만 골라서 처리
$('div[style], div ul[style]').each(function() {
var styleAttr = $(this).attr('style');
if (styleAttr) {
// 정규식을 사용하여 background-color와 color 속성만 찾아 제거
var newStyle = styleAttr
.replace(/background-color\s*:\s*[^;]+;?/gi, '')
.replace(/color\s*:\s*[^;]+;?/gi, '');
// 불필요한 공백/세미콜론 정리
newStyle = newStyle.trim().replace(/;$/, '');
// style 속성을 새로 설정
$(this).attr('style', newStyle);
}
});
// background-color 속성이 포함된 span 요소만 선택
$('span[style*="background-color"]').each(function() {
// 실제로 적용된 CSS 배경색(예: rgb(246, 225, 153)) 가져오기
var bgColor = $(this).css('background-color');
// rgb(...) 또는 rgba(...)에서 숫자만 추출하는 정규식
var matched = bgColor.match(/\d+/g);
if (matched) {
var r = parseInt(matched[0], 10);
var g = parseInt(matched[1], 10);
var b = parseInt(matched[2], 10);
// 밝기 계산 (가중치 사용)
var brightness = 0.299*r + 0.587*g + 0.114*b;
// 밝기에 따라 글자색 설정
if (brightness < 128) {
// 어두운 배경 -> 흰색 폰트
$(this).css('color', '#ffffff');
} else {
// 밝은 배경 -> 검정 폰트
$(this).css('color', '#000000');
}
}
});
});
</script>
- DOM 트리가 완성된 후 실행되도록 $(document).ready() 안에 위치시키므로, DOM 요소에 안전하게 접근할 수 있다.
html이 파싱되며 dom이 구성되는 과정과 css js가 적용되는 시점들을 생각해보는 재밌는 기회였다
jquery를 처음 써보는데 dom 요소에 아주 쉽게 접근할 수 있는것과, dom 요소의 값이 적용되는 방식을 생각하며 요소값을 추가하는 것도 꽤나 재밌었다 😀
참고자료
https://soobysu.tistory.com/137#solution-1
https://ko.javascript.info/script-async-defer
https://velog.io/@anjaekk/JS-Script삽입-위치head-body-async-defer-비교
https://jizard.tistory.com/307?utm_source=chatgpt.com
https://sunnybong.tistory.com/436
혹시 문제가 있다면 말씀해주세요
같은 문제를 겪고 계신 분들에게 도움이 되길..👍🏻