メインコンテンツへ移動

CSST(CSS Text Transformation)

無料2016-05-14#CSS#JS#CSST是什么#跨域文本传输#跨域方法

CSSTの類義語はJSONPであり、SASSやPostCSSのようなものではありません。

1. CSSTとは何か

CSSTの類義語はJSONPであり、SASSやPostCSSのようなものではありません。つまり、JSONPでできることは、(CSS3環境下であれば)CSSTでも可能です。

Ajaxはクロスドメインに対応していませんが、JSONPはAjaxのクロスドメイン対応パッチのようなものです(もちろん他にもクロスドメインの手法はありますが、JSONPが最も広く使われています)。

CSSTの最大の制限は、CSS3をサポートする環境にのみ適用可能であることですが、実際に使うかどうかは別として、その考え方や原理は非常に興味深いものです。

2. 実装原理

1. クライアント側(ブラウザJS)

  1. リクエストの送信

head内に<link>を挿入し、href属性を通じてリクエストを送信します。

  1. レスポンス受信の準備

目に見えないspanを作成し、そのanimationstartイベントを監視します(そのためCSS3環境が必要です)。

2. サーバー側(node/PHP...)

  1. スタイルの返却(idを通じて非表示のspanに適用されます)

スタイルの内容は2つの部分に分かれます:1. content(CSSプロパティのcontentを使用して、ビジネスロジックが返却する文字列を格納します)、2. animation(レスポンスが返ってきたことをクライアントに通知します)。

サーバー側はこの処理のみを行い、クライアント側はレスポンスを受け取るとspanのcontent内容を取り出し、テキスト転送が完了します。

3. 詳細な問題(技術的手法)

  1. <link>の読み込み完了をどのように監視するか?

ネット上の資料を収集したところ、一般的な方法はタイマーやonpropertychange、DOMAttrModifiedを使用することでした。

CSS3の利用シーンであることを考慮し、アニメーション開始(animationstart)イベントをキャッチする方法を採用しています。

onpropertychangeDOMAttrModifiedイベント、およびより新しい MutationObserver は互換性の面で多くの問題を抱えていますが、animationstartイベントは比較的良好です(Android 2.3以下、IE6-IE9は非対応)。アニメーションイベントはCSS3アニメーションモジュール仕様の一部であるため、CSS3アニメーションをサポートするUA(ユーザーエージェント)であれば、対応するアニメーションイベントもサポートしているはずだからです。

  1. 特殊文字("、'、\、\n、\r、\t)をどのように転送するか?

ChromeとSafariでは、contentスタイルプロパティの文字解析が一致しません。

未知の解析ルールの影響を避けるため、一律base64エンコーディングを使用します。

ブラウザ環境下でのBase64のエンコード/デコードは比較的容易であり、他の特殊文字をサポートする必要があるシーンにも適しています。

3. メリットとデメリット

メリット:もしインターフェースが攻撃された場合、その影響はJSONPよりも少し小さくなります(linkタグはscriptタグよりも安全です。後者は注入されたコードが直接実行されますが、前者はスタイルにのみ影響します)。

P.S. もしインターフェースが完全に攻撃されてしまった場合、このようなわずかな防御策が果たして重要な役割を果たせるのでしょうか?

デメリット:

  • CSS3環境のみをサポート

  • DOM操作がJSONPよりも多い(リクエストごとにlinkとspanを1つずつ追加/削除する必要があります。JSONPはscriptを1回追加/削除するだけです。また、非表示のspanの追加/削除やスタイルの更新により、ページの一部でリフローが発生する可能性があります)。

したがって、CSSTの使用は推奨しません。JSONPの方が明らかに便利で実用的です。この記事は、このような考え方や原理を知っておく価値があるということを伝えたかっただけです。

もしどうしても使いたいのであれば、CSS3をサポートしていない、あるいは部分的にしかサポートしていないUAへの配慮も必要であり、機能検出(元のプロジェクトではまだ追加されていません)を充実させる必要があります:

var animation = false,
    animationstring = 'animation',
    keyframeprefix = '',
    domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
    pfx  = '',
    elm = document.createElement('div');

if( elm.style.animationName !== undefined ) { animation = true; }    

if( animation === false ) {
  for( var i = 0; i < domPrefixes.length; i++ ) {
    if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
      pfx = domPrefixes[ i ];
      animationstring = pfx + 'Animation';
      keyframeprefix = '-' + pfx.toLowerCase() + '-';
      animation = true;
      break;
    }
  }
}

(以上のコードは Detecting CSS animation support - CSS | MDN より引用)

より良い互換性を実現するにはコードの手動リファクタリングが必要ですが、まあ、知識として知っておく程度で十分でしょう。

参考資料

コメント

コメントはまだありません

コメントを書く