NOMO.asia

Userscript 를 이용해 커스텀 CSS를 적용하는 몇 가지 방법을 정리해보았다. Chrome의 Tampermonkey 확장기능과 Firefox의 Violentmonkey 확장기능을 기준으로 작성하였다.


1. GM_addStyle 함수의 사용

GM_addStyle 함수는 입력 인자로 적은 text 를 css 로 추가해주는 함수이다. 사용 전 메타 블록에 @grant GM_addStyle을 추가해주어야 한다. GM_addStyle 에 대한 설명은 다음의 링크를 참고 (https://sourceforge.net/p/greasemonkey/wiki/GM_addStyle/)


예시1

// ==UserScript==
// @name         MyUserscriptName
// @namespace    myNamespace
// @version      0.0.1
// @description  Description
// @author       You
// @include      *
// @grant        GM_addStyle
// ==/UserScript==

GM_addStyle(`
  @import url('https://fonts.googleapis.com/css?family=Noto+Sans+KR:400,900');
  body { font-family: 'Noto Sans KR', serif !important; font-weight:400 !important;}
`);

css의 import 규칙을 이용해 구글 웹폰트 적용을 위한 외부 css 파일을 불러오고, 해당 웹폰트를 적용하는 예시이다.


위의 예시에서 나름 유용한 부분은 GM_addStyle 함수를 이용할 때 ', " 가 아닌 ` 로 css 텍스트를 묶으면 줄바꿈이 자유로워 코드 작성이 매우 편해진다는 부분이다. ES6에 Template_literals 라고 새로 생긴 것이라고 하는데 어차피 UserScript 를 적용할 브라우저는 Chrome, Firefox 등의 최신 브라우저일 것이므로 마음껏 쓰고있다. 만약 ` 를 쓰지 않으면 아래와 같이 해주어야 한다.


예시2

// ==UserScript==
// @name         MyUserscriptName
// @namespace    myNamespace
// @version      0.0.1
// @description  Description
// @author       You
// @include      *
// @grant        GM_addStyle
// ==/UserScript==
/*jshint multistr: true */

GM_addStyle("\
  @import url('https://fonts.googleapis.com/css?family=Noto+Sans+KR:400,900');\
  body { font-family: 'Noto Sans KR', serif !important; font-weight:400 !important;}\
");

당연히 예시 1의 방법이 더 편하다.

만약 적용이 되지 않고 콘솔창에 GM_addStyle 이 존재하지 않는 함수라고 뜬다면 greasemonkey 버전 간 호환 문제일 가능성이 크다. 다른 확장기능을 사용하거나, 메타 블록에 아래의 두 줄을 추가하자.

// @require     https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @grant       GM.addStyle


다만 css 내에서 import 규칙을 사용하는 경우… 커스텀 CSS를 적용하려는 웹사이트는 당연히 내가 만든게 아닐 확률이 높고, 처음부터 css 의 import 규칙을 이용하려고 디자인된게 아니다보니 웹사이트에 따라 import 규칙이 종종 씹히는 경우가 있다. 이럴 때는 아래의 방법들을 사용하면 편하다.



2. @resource 규칙 사용하여 외부 css 파일 불러오기

메타 블록에 resource 규칙을 사용한다. resource 규칙을 이용하면 css 파일 뿐만 아니라 이미지 파일 등 다양한 외부 파일을 참고할 수 있다. resource 에 대한 설명은 다음의 링크를 참고(https://wiki.greasespot.net/Metadata_Block#.40resource). 


해당 경로에 있는 파일을 불러오기 위해 GM_getResourceText 와 같은 함수를 함께 사용해주어야 하며, 자세한 설명은 아래의 예시로 대체한다.


예시

// ==UserScript==
// @name         MyUserscriptName
// @namespace    myNamespace
// @version      0.0.1
// @description  Description
// @author       You
// @include      *
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @resource     my_CSS    https://fonts.googleapis.com/css?family=Noto+Sans+KR:400,900
// ==/UserScript==

var my_FONT = GM_getResourceText('my_CSS');
GM_addStyle(my_FONT);
GM_addStyle("body {font-family: 'Noto Sans KR', serif; font-weight:400;}");

3. head 에 append 하기

head 에 스크립트를 append 하는 방법이다.


예시

// ==UserScript==
// @name         MyUserscriptName
// @namespace    myNamespace
// @version      0.0.1
// @description  Description
// @author       You
// @include      *
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
// ==/UserScript==

var cssText = `
  
  
`;

$('head').append(cssText); 

앞선 두 방법은 userscript 확장 기능의 종류나 업데이트에 따라 아주 간혹 적용이 안 되는 경우가 있었다. 하지만 이렇게 head에 스크립트를 바로 삽입하는 경우는 아직까지 실패해본 경험이 없다. 즉 확장기능/브라우저별 호환성이 가장 좋은 방법이라고 개인적으로 생각한다.


다만 run-at(https://wiki.greasespot.net/Metadata_Block#.40run-at) 을 무엇으로 선언하느냐, head에 스크립트를 삽입하는 코드를 어떤 위치에 선언하느냐($(document).ready 등)에 따라 앞선 두 방법보다 아주 미세하게 느린 느낌을 받았다. 경우에 따라 세가지 방법을 잘 조합해서 쓰면 된다.



그 외

$('body').css('fontSize','14px') 와 같은 방법으로도 가능. CSS를 적용할 요소가 많지 않을 때 쓸 수 있지만, 동적으로 생기는 요소의 경우 요소가 생긴 뒤에 이와 같은 코드가 실행되어야 한다는 제약이 있다.