[PR]馳凡g\
g選

外部スタイルシート切り替えスクリプトとは

スタイルシートは、代替スタイルシートを準備することで複数のデザインを閲覧者に選んでもらえるようにすることが出来ます。FirefoxやOperaなどでは、ブラウザメニュー → 表示 → スタイルの変更 でスタイルシートを切り替えられます。

ところが、Internet ExplorerやSafariなどではスタイルの変更が出来ません。また、各ページで統一されたデザインを作成しても、ページを移動すると元の(優先スタイルシートの)デザインに戻ってしまいます。

そこで、スタイルの変更を実装していないブラウザでもスタイルの変更が出来るように、またページを移動しても選択されたデザインを維持できるようにする機能をウェブページに追加するのが、この外部スタイルシート切り替えスクリプトです。

ダウンロード

利用許諾

本スクリプトはBSDライセンスに従うものとします。よくわかんないけど。

使い方

  1. stylechange.jsを開いて初期設定を行います
    • 最初に必要な設定はcookiePathくらいです。cookiePathにはウェブサイトのトップページのパスを指定します。以下例。
      トップページ: http://www.example.com/users/index.html → cookiePath = '/users/'
      
  2. <head></head>内にlink要素を追加します
  3. <head></head>内の全てのlink,style要素より下でstylechange.jsを呼び出します
    • 下記の例を参考に<script>タグを追加してください。
  4. 切り替えフォーム挿入用のタグをページに追加します
    • 切り替えフォームが必要なければこの項は飛ばしてください。
    • 切り替えフォームを表示させたい位置に<span id="stylechange"></span>を追加します。idが正しければdiv要素などでもかまいません。

以上!

<html>
<head>
<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="hoge.css" title="hoge">
<link rel="alternate stylesheet" href="fuga.css" title="fuga">
<link rel="alternate stylesheet" href="piyo.css" title="piyo">
<!--
  この例ではbase.cssが固定スタイルシート
  hoge.cssが優先スタイルシート
  fuga.css, piyo.cssが代替スタイルシートになります
  切り替えフォームにはタイトルが指定されたものが表示されます
  disableStyleに指定したタイトルは使用しないでください(初期値'_disabled')
-->

<script type="text/javascript" src="stylechange.js" charset="utf-8"></script>
</head>
<body>

<span id="stylechange"></span>
<-- ↑ここに切り替えフォームが表示されます -->

〜 以下自由に 〜

サンプルはこのページ。

特徴

  • スタイルの変更を感知してページを移動しても変更したスタイルグループを維持
  • スタイルの変更フォームをページに追加する機能
    • これによりスタイルの変更機能のないブラウザでも代替スタイルシートを利用できるようになります
  • 移動後のページに切り替えたスタイルがなかったら優先スタイルシートを利用
  • XHTML/HTML どちらでも動作?
  • スクリプトで新しいスタイルシートを指定することも可能
  • onloadを使用しないのでスタイルの切り替えがスムーズ
  • Web標準に準拠したブラウザであればほぼ動作
    • WinXP IE6, 7, 8 beta1
    • WinXP Netscape9.0
    • WinXP Firefox2.0, 3.0
    • WinXP Opera9.50 beta
    以上で問題なく動作することを確認しました。古いブラウザは完全に無視
  • グローバル変数をあんまり汚染しない
    • グローバル変数として使用しているのは“StyleChange”のみなので安心して他のjsライブラリと一緒に使えます
  • style要素のグループ化に対応
    • WinIE, Mozilla, Operaで動作確認。Safariではうまくいきません…

機能/詳細

スタイルの自動変更/変更を維持

ページのロード時に自動的に優先スタイルシートに切り替えます。ページの閲覧者によってスタイルシートの変更が行われていた場合には変更の情報をクッキーに保存し、移動先のページに同じタイトルのスタイルシートグループがあればそのスタイルシートに自動的に切り替えます。移動先に同じタイトルのグループがなければ移動先のページの優先スタイルシートに切り替えます。

スタイルの変更のタイミングはstylechange.jsを読み込むscript要素の準備が完了したときです。script要素の準備が出来た時点で実行されるので、全てのlink,style要素より下で呼び出さないとうまく動作しない場合があります。

スタイルの切り替えのためのフォームを自動挿入

設定で指定したIDの要素にプルダウン形式のフォームを挿入します。フォームにはlink,style要素のtitleをリスト化して表示します。

挿入されるフォームのhtmlは以下のようになります。(DOMを操作して挿入します。実際には見栄えのための空白はありません)

    スタイル:<select onchange="StyleChange.select()">
        <option value="hoge" selected="selected">hoge</option>
        <option value="fuge">fuga</option>
        <option value="_disabled">なし</option>
    </select>

また、'スタイルを適用しない'の項目を選択すると、優先スタイルシート、代替スタイルシートが無効化されます。ブラウザのスタイルシートを無効化する機能とは違い、固定スタイルシート(タイトルのないlink,style要素)は有効のままです。

スタイルシートの追加

設定で指定したスタイルシートをページに追加します。追加するスタイルシートにはタイトルとalternateの有無を指定できるので、固定,優先,代替スタイルシートとして追加することができます。

クッキー

切り替えフォームからスタイルを変更したとき、またはonunload時(ページから離れるとき)に使用されているスタイルシートがデフォルトのスタイルシートと異なるときに、クッキーに適用されているスタイルシートのタイトルが記録されます。設定でクッキーのドメイン,パス,有効期限を指定できます。有効期限を0にするとブラウザを閉じるまで有効となります。以下クッキーの詳細

Set-Cookie: stylechange=sheetTitle; domain=Domain; path=Path; expires=Expires

対応するブラウザ

Web標準に準拠したブラウザであればたぶん動作すると思います。以下動作確認の結果

環境 状況備考
WinXP IE6, 7, 8 beta1
WinXP Netscape9.0
WinXP Firefox2.0, 3.0
WinXP Opera9.50 beta
WinXP Safari3.1 Safariがデフォルトだと認識したstyle要素しかスタイルの変更が反映されない

デフォルトのスタイルシート

<meta http-equiv="Default-Style" content="sheetTitle">

上記をhead要素に追加することでデフォルトのスタイルシートを指定することが出来ます。この指定はstylechange.jsの設定より優先されます。

style要素のグループ化

style要素にtitle属性を設定することでstyle要素を代替スタイルシートとしてグループ化することが出来ます。しかしWeb標準として明記された機能ではないので、この機能の利用は推奨しません。また、Safariではtitle属性を指定したstyle要素を正しく切り替えることが出来ません。

stylechange.js minified(縮小版)について

Ver 2.00で大幅な修正を行った結果、機能の割にちょっとサイズの大きいスクリプトになってしまったので縮小版を作りました。Ver 1.05以前とほぼ同じサイズまで縮小してあります。スクリプト本体部分の可読性を完全に無視していますが、短く記述できるようにプロパティが増えている以外は通常版と機能は全く同じですので、中身を読みたい方以外には縮小版をお勧めします。

ヘルプ

自動挿入される切り替えフォーム以外でスタイルを変更したい

グローバル変数のstylechangeにStyleChangeオブジェクトが入っています。stylechange.change(title)を実行すればスタイルを切り替えることが出来ます。以下サンプル

<ul>
    <li><a href="javascript:void 0;" onclick="stylechange.change(this.innerHTML)">default</a></li>
    <li><a href="javascript:void 0;" onclick="stylechange.change(this.innerHTML)">scapesheep</a></li>
    <li><a href="javascript:void 0;" onclick="stylechange.change(this.innerHTML)">andromeda</a></li>
    <li><a href="javascript:void 0;" onclick="stylechange.change(this.innerHTML)">simply failed</a></li>
</ul>

スタイルは変更してないけどクッキーをセットしたい

グローバル変数のstylechangeにStyleChangeオブジェクトが入っています。stylechange.setCookie(title)を実行すればクッキーをセットできます。しかしスタイルを変更した場合、unload時にクッキーが書き換わりますのでご注意を。以下サンプル

stylechange.setCookie('andromeda');alert(document.cookie);
stylechange.setCookie('simply faild');alert(document.cookie);

既知の問題

  • ブラウザのスタイル変更機能を使用して優先スタイル→代替スタイル→優先スタイルとするとスタイルの切り替えを感知できない
    • つまりスタイルの変更があったのにcookieを上書きできない
    • DOMAttributeModifiedとか考えたけどいろいろと問題が多いので「仕様です」ということにする
  • Safariでstyle要素のグループ化がうまくいかない
    • Safariがデフォルトだと認識したstyle要素しか反映されてないのでそのスタイルしか切り替えが効かないみたい
  • macIEでどうなるやら

おまけ

スタイルシート対応状況

ブラウザ stylechange.js WinIE6, 7, 8 Firefox2.0, 3.0 Opera9.50 beta WinSafari3.0
document.styleSheets 全てのstyleSheetオブジェクト全てのstyleSheetオブジェクト全てのstyleSheetオブジェクト全てのstyleSheetオブジェクト解析時に適用されたstyleSheetオブジェクト
<link rel=stylesheet> 固定スタイルシート 固定スタイルシート 固定スタイルシート 固定スタイルシート 固定スタイルシート
<link rel=stylesheet title> 優先スタイルシート 優先スタイルシート 優先スタイルシート 優先スタイルシート 優先スタイルシート
<link rel=alternate stylesheet> 各ブラウザに委ねる 固定スタイルシート 無効 無効 固定スタイルシート
<link rel=alternate stylesheet title>代替スタイルシート 代替スタイルシート 代替スタイルシート 代替スタイルシート 代替スタイルシート
<style> 固定スタイルシート 固定スタイルシート 固定スタイルシート 固定スタイルシート 固定スタイルシート
<style title> 代替スタイルシート 固定スタイルシート 代替スタイルシート 固定スタイルシート 代替スタイルシート
<meta http-equiv=Default-Style> 対応 対応 対応 対応 対応
HTTP header: Link 未調査 未調査 未調査 未調査 未調査
HTTP header: Default-Style 未調査 未調査 未調査 未調査 未調査

謝辞

createElement,createElementNSを使い分けるための関数としてCSS切替スクリプト(徒委記)から一部頂きました。ありがとうございます!

履歴

  • 08.06.02 20:42
     - Ver2.01 クッキーが存在しないときに存在しないスタイルを選択すると優先スタイルシートに切り替わる不具合を修正
    
  • 08.06.02 02:24
     - Ver2.00 無駄にオブジェクト指向に
     - style要素のグループ化に対応
       - style要素にtitleを指定することでstyle要素がtitleのグループに追加されます
       - Safariではうまく動きません…style要素のグループ化はなるべくしないほうがいいです
     - Default-Styleの指定に対応
       - meta要素の指定のみです。HTTP headerで指定されても分かりません…
     - 指定されたタイトルのスタイルグループが存在するか確認するように変更
       - グループが存在しないときは優先スタイルを使用します
     - 切り替えフォームの挿入のタイミングをDOMContentLoaded時に変更
     - スタイルの変更時にwindowにforcusしないように変更
     - 閲覧者によってページのスタイルが変更されていない場合はonunloadイベントを起こさないように修正
     - addElementIdで指定したidの要素が存在しない場合にエラーになる不具合を修正
     - cookieDomain,cookiePassを指定しないとクッキーの値が壊れる不具合を修正
     - 同じtitleの要素が複数ある場合にプルダウンに同名のリストが複数表示される不具合を修正
     - 他のスクリプトのonloadイベントを上書きしてしまう不具合を修正
     - Opera, IE6以降, Safariで動作することを確認
    
  • 06.10.07 16:22
     - Ver1.05 OOP風DOMチックに記述を変更
     - 切り替えフォームを挿入する要素のidを変えられるように変更
     - 設定によってselect要素が閉じていない問題を修正
     - IE7RC1で動作確認
    
  • 06.06.14 02:44
     - Ver1.04 cookieの記述を変更
    
  • 06.06.04 10:48
     - Ver1.03 キャッシュがない場合にスタイルの自動切り替えで優先スタイルシートを選択してしまう不具合を修正
     - 'スタイルを適用しない'の項目の表示を選択できるように変更
    
  • 06.06.04 07:15
     - Ver1.02 option要素のselectedをselected="selected"に変更
    
  • 06.06.04 05:37
     - Ver1.01 Mozilla系ブラウザで切り替えフォームが表示されない問題を修正
    
  • 06.06.03 21:45
     - Ver1.00 スクリプト公開