Tuesday, 14 May 2013

HTMLで文字詰め出来るJavaScriptとjQuery

日頃WEBのテキストで句読点および括弧類が連続して出現する場合の詰め処理をしたくてどうしたものかと思案していたら、素晴しいJavaScript(とjQueryの混合)を発見。このスクリプト、要はペアカーニングを任意に設定できてしかも2つの括弧類連続を設定するだけで括弧類が3つ以上連続してもちゃんと詰めてくれる。いやはやありがたや。ということで今回参考というか丸々活用させていただいたのはFLAutoKerning.jsというスクリプト。
感謝深謝。

カーニングのペアを自動処理

今回の組版の設定は、基本ベタ組みで、句読点および括弧類が2つ連続した場合「全角二分取り」になるような、つまりは二分分詰まるような、オーソドックスな設定で試してみる。そして今回の句読点および括弧類は
起こし括弧類:「『([{〈《【〔
受け括弧類:」』)]}〉》】〕
句読点類・中点:、,。.・
の計21種の組合せに詰め設定を施すが、この組合せを配列にて自動化した。
jQuery(function($){
 var pncPrn = ["」","』",")","]","}","〉","》","】","〕","「","『","(","[","{","〈","《","【","〔","、",",","。",".","・"];
 for (var x=pncPrn.length; x--;){
  for (var y=pncPrn.length; y--;){
   p[pncPrn[x] + pncPrn[y]] = -0.6;
  }
 }
});
上記jQueryにて設定した句読点括弧類の【組合せ】をFLAutoKerning.js内カーニングペア定義の箇所に追加(不要な組合せもあるが、処理上別段問題ないのでそのままにする)。

行頭文字の処理

実はこのスクリプト、行頭の1文字もカーニング設定できる。つまり、行頭1字下げしない組み設定の時、起こし括弧類が行頭に来ると直前が二分アキになるのを詰めることができる。これも配列にて自動化した。
jQuery(function($){
 var Prn = ["「","『","(","[","{","〈","《","【","〔"];
 for (var z=Prn.length; z--;){
  p[Prn[z]] = -0.6;
 }
});
このjQueryもFLAutoKerning.js内行頭専用の箇所に追加。

行末文字の処理は…

このスクリプトでは出来ない。というか組版ソフトはどうやって行末処理のために行末の判別をしているのか、実に不思議だと改めて思う次第。

設定値「-0.6」って何なのさ?

ワタクシのデモページの文字サイズはrem単位にて、rootサイズ1rem(10px相当)、本文サイズは1.2rem(12px相当)に設定しているので、このとき二分は本文の半分の0.6rem(6px相当)になるので。
そうそう、このスクリプトはem単位に設定されているので、その部分をrem単位に変更した(下記の2箇所)
if(space!=0)
 char2 = "<span class='kerning01' style='letter-spacing:" + space + "rem'>" + char + "</span>";
     
//行頭約物の処理
if(i == 0 && kerningInfo[char])
 char2 =  "<span class='kerning02' style='margin-left:" + kerningInfo[char] + "rem'>" + char2 + "</span>";
こうして完成したデモページに、今回は「詰め解除」と「詰め設定」の2つのボタンを設置して詰め具合が判るようにした。
デモページ【WEB TYPOGRAPHY KERNING

Thursday, 9 May 2013

JavaScriptとjQueryで文字サイズ・行高・行取り・見出し行数から見出しのマージンを自動計算

ワタクシがwebデザイン上一番気にするのが見出しのマージン。いつもその時の感覚で決めるが、しっくり来ないことが多々ある。何か巧い方法が無いものかと『文字の組方ルールブック ヨコ組編』の「見出しの構造と組方」を眺めていて、自動計算出来るかもと思いjQueryメインに適宜JavaScriptを組み込みスクリプトなるものを書いてみた。
2013.5.14追記

参照

ほか、色々なサイト・ブログを参照させていただいた。深謝。

注意

なにせjQueryはおろかJavaScript、いやプログラミング全般に素人なので間違ってたりする可能性があるので、使用時は自己責任でお願いする。

実作したweb組版

本文の文字サイズ・1行の字詰・行間(行送り)などを決めると版面が決まる。見出しもその版面に則り「行取り」の方法でその上下のアキを決めていく。具体的には下図をご覧あれ。本文だけでなく見出しも行に綺麗に乗っているのがわかる。
本文サイズ12px、行高22px、行間10px、42字詰。各見出しサイズなどは図の通り。

完成形をブラウザで表示後キャプチャし、イラレで作成した水色の版面上にキャプチャ画像を配置した。

web組版の注意点

行送りの設定方法がDTPと異なる。
webの行送りはline-heightで設定するが、これは厳密には文字通り行の高さを設定するもので、アキの付き方は以下の図の通りになる。

本文上下のグレー網がline-heightで設定されるアキ

これを踏まえて版面設計や見出しのマージンを算出する。

見出しマージンの計算式

ということで、計算式を導くために、下図のように必要な部分を設定。
var bFont = body要素(本文)のfont-size
var bHeight = body要素(本文)のline-height
var hFont = 見出しのfont-size
var hHeight = 見出しのline-height
var hGyodori = 見出しの行ドリ行数
var hGyosu = 見出しの行数
var hMargint = 見出しの上マージン
var hMarginb = 見出しの下マージン

hMargint : hMarginbの比率をj : kとする
見出しが1つの場合
見出しが1つの場合

見出しの上下マージンの計算式は各々、
hMargint = j*(hGyodori*bHeight-hGyosu*hHeight)/(j+k)
hMarginb = k*(hGyodori*bHeight-hGyosu*hHeight)/(j+k)
j : k = 1 : 1の時、
hMargint = hMarginb = 0.5*(hGyodori*bHeight-hGyosu*hHeight)
j : k = 8 : 5(黄金比の近似比)の時、
hMargint = 8*(hGyodori*bHeight-hGyosu*hHeight)/13
hMarginb = 5*(hGyodori*bHeight-hGyosu*hHeight)/13
という風になる。
見出しが2つ以上の場合
見出しが2つ以上連続する場合

上記「見出しが1つの場合」に同じ計算式で算出でき、見出し間のマージンは上下見出しの下マージンと上マージンを足せば良い。

今回使用したjQueryやJavaScriptの留意点

  1. 本文や見出しのfont-sizeやline-heightの値は、css()で取得するが「16px」というように単位付きの文字列として返してくる。今回は数値として使いたいので、JavaScriptのparseFloat関数で文字列を数値化する必要がある。
  2. 本文や見出しのfont-sizeやline-heightは今回CSS3のrem単位で規定しているが、上記1.でrem単位で規定した値を取得するとpxに変換される。
  3. 本文や見出しのfont-sizeやline-heightはどちらも偶数か、またはどちらも奇数が好ましい。行高の計算でline-height-font-sizeの値を1/2にして行の上下に配分するが、そのとき小数点以下(0.5)が出ないようにするため。小数点はブラウザ側で丸めるが、ブラウザごとに丸め方が異なりレイアウトが崩れる可能性がある、らしい。
  4. 最終的に算出されたマージンの値は、Math.round()で小数点以下を四捨五入して整数値になるようにしている。上下マージン比j : kによりマージン値が無理数の場合があるので、それを丸めるために。
  5. 見出しが連続する場合、絞り込むため、ある要素の「前」にあたる兄弟要素を抽出するjQueryのprev([expr])関数を使うが、$("h4").prev("h3").prev("h2")のように連ねても使える。この場合、h2・h3・h4と連続しているh2のみにマージン設定ができる。



こうしてあとはJavaScriptとjQueryとで記述すれば完成。

スクリプトは【デモページ】のソースを参照していただければ。

Thursday, 2 May 2013

CSSボタンでテキストを天地中央に揃えるとき、なぜボタン高と行高を一緒にするのか

表題の件が気になり調べたものを共有した方がイイかなと思い公開してみる。
自身の中でまだよく噛み砕けていないので判りづらい箇所があるかと思うが、そこはご寛恕を。

参考

インライン要素とは何か

文書構造を構成するブロックレベル要素内の特定箇所にある特定の機能や論理的な意味を付加する要素をいう。それ自身の前後に改行を生成しない。例としては、a要素、em要素、span要素など。
インライン要素には非置換要素と置換要素とがある。今回は置換要素には触れない(置換要素の代表例はimg要素)。

非置換要素とは何か

要素に囲まれた内容がそのまま表示される要素。HTMLやXHTMLの要素の大半は非置換要素である。

インライン非置換要素の特徴

  • widthとheightは適用されない。
  • 背景はコンテンツエリアとpaddingに適用される。
  • 上下marginは、事実上適用されない。
  • 左右paddingは、要素の先頭と末尾のみに適用される。
  • 上下paddingは、要素の背景を上下に伸ばすが、行の高さに影響しないため、背景色がある場合は上下の行(実際は上の行)に重なってしまう。

line-heightは何を制御しているか

行高を指定するline-heightは単純に行間を制御しているのではなく、leadingという、コンテンツエリアの上下にある余白を制御している。leadingはline-heightとfont-sizeとの差であり、この差を等分してコンテンツエリアの上下に加えることによって行間が決まる(コンテンツエリア+leadingをインラインボックスという)。

コンテンツエリアとは、インライン非置換要素では、要素内の全ての文字を繋ぎ合わせたボックスでfont-sizeの値と同じ高さになる。
図解すると以下の通り。


つまり、line-heightが設定されたテキストが1行のみの時は、テキストは自ずとインラインボックスの天地中央に配置されることになる。

なぜa要素に「display: block;」を指定するのか

インライン非置換要素であるa要素に、widthとheightを適用させ、上記line-heightの設定により天地中央に揃えられ且つ背景色部分にもリンクが及ぶようにするため。

ボタンのHTML
<body>
        <div>
                <a href="#">BUTTON</a>
        </div>
</body>
ボタンのCSS
a {
        /* ブロックレベル要素化 */
        display: block;
        
        /* サイズ指定 */
        width: 200px;
        height: 50px;
        
        /* 縦横中央揃え */
        text-align: center;
        line-height: 50px;
        
        /* 色指定 */
        color: #FFFFFF; 
        background-color: #0099B5;
        
        /* その他 */
        font-size: 12px;
        text-decoration: none;
}
a:hover {
        color: #FFFFFF;
        background-color: #3E4051;
}


※水色の部分にもリンクが及んでいる。

※「display: block;」を指定せずともpaddingを上下左右に適用してボタンの作成は可能。しかし、上下paddingは行の高さに影響せず、また上下marginも事実上適用されないため、ボタン自身にcssを適用してボタンの位置を調整することが出来ない(他の要素に依存)。

わざわざa要素に「display: block;」を指定せずとも、a要素を囲っているdiv要素にwidthとheight、background-colorを適用してはいいのでは?

a要素はインライン非置換要素であるため、a要素の適用範囲はコンテンツエリアのみであり、div要素からa要素のコンテンツエリアを引いた範囲にはリンクが及ばないため、ボタンではなく只のテキストリンクになってしまう。

ボタンのHTML
<body>
        <div>
                <a href="#">BUTTON</a>
        </div>
</body>
ボタンのCSS
div {
        /* サイズ指定 */
        width: 200px;
        height: 50px;
        
        /* 縦横中央揃え */
        text-align: center;
        line-height: 50px;
        
        /* 色指定 */
        color: #FFFFFF;
        background-color: #0099B5;
        
        /* その他 */
        font-size: 12px;
}
a {
        color: #FFFFFF; 
        text-decoration: none;
}
a:hover {
        color: #FFFFFF;
        background-color: #3E4051;
}


※リンクはテキスト部分のみで、水色の部分にまで及んでいない。

Wednesday, 1 May 2013

jQueryでHOVERした以外の文字が薄くなる縦型ナビに背景色変更も加味

最近制作した案件にて採用したHOVER以外のボタンが薄くなる縦型ナビについて解説をば。
今回参考にさせていただいたのは、webOpixelさんの記事「jQueryで作るマウスオーバーアニメーションするテキストタイプの縦型ナビゲーション10種」内の「8.マウスオーバー以外のボタンを薄くする。」であります。深謝。

メインナビのみの縦型ナビ

HTML
<ul id="mainNavi">
    <li><a href="#">works</a></li>
    <li><a href="#">projects</a></li>
    <li><a href="#">bibliography</a></li>
    <li><a href="#">contact</a></li>
    <li><a href="#">about</a></li>
</ul>

※URLは見やすさのために#に置き換えて省略。

CSS
#mainNavi {
    width: 192px;    ・・・・1:必須
    text-transform: uppercase;    ・・・・2:任意
    border-bottom: dotted 1px #BAC3C9;    ・・・・3:任意
}
#mainNavi li {border-top: dotted 1px #BAC3C9;}    ・・・・4:任意
#mainNavi li a {
    display: block;    ・・・・5:必須
    padding: 0.8em 0.5em 0.5em;    ・・・・6:必須
}

CSS指定の留意点:
  1. width指定をしないとwidth: 100%;に同じとなり可能な限りの幅になる。
  2. 今回のナビではラテン文字全てを大文字に指定したので。
  3. 今回は各ナビ上下に境界線を4.にてtop側で指定、これではナビの最後のみbottomの境界線が指定できないのでここで指定。
  4. 今回は各ナビ上下に境界線をtop側で指定。
  5. この指定で<a>タグをブロック要素にし、ナビの余白を含んだ背景に色が付くようにしている。
    (逆にしないと、<a>タグはインライン要素のままで、リンク文字部分のみに背景色が付くだけで且つ上下パディングが隣接行やボーダーラインに被ってしまう)
  6. ワタクシは極力高さ指定しない主義なので、その代わりにパディングにてリンク文字周りの余白を指定している(上記CSSの最終行がそれ)。

jQuery
$(function() {
    var nav = $('#mainNavi li a');
    nav.hover(
        function(){
            nav.not(this).stop().animate({color : '#D1D7DB'},700);
        },
        function () {
            nav.not(this).stop().animate({color : '#3E4051'},700);色
        }
    );
});

※参考:「jQueryで作るマウスオーバーアニメーションするテキストタイプの縦型ナビゲーション10種」内の「8.マウスオーバー以外のボタンを薄くする。」より
not(this)がミソということらしい。これでHOVERした以外のナビ文字が薄くなる。

HOVER時に背景色も変更させるための改造
この改造のポイントは、背景色の変更はCSSではなく、全てjQueryにて行なうということ。具体的には以下の通り、元の背景色と背景色変更のscriptを上記既出のjQueryに追加。
$(function() {
    $('#mainNavi li a').hover(
        //HOVER時
        function(){
            $('#mainNavi li a').not(this).stop().animate({color : '#D1D7DB', backgroundColor : '#fff'},700);
            //HOVERした以外のナビの文字色と背景色
            $(this).stop().animate({color : '#0099B5', backgroundColor : '#F4F5F6'},700);
            //HOVERしたナビの文字色と背景色
        },
        //HOVERが外れた時
        function () {
            $('#mainNavi li a').not(this).stop().animate({color : '#3E4051', backgroundColor : '#fff'},700);
            //HOVERした以外のナビの文字色と背景色
            $(this).stop().animate({color : '#3E4051', backgroundColor : '#fff'},700);
            //HOVERしたナビの文字色と背景色
        }
    );
});
そして、参考元のjQueryでは「var nav = $('#mainNavi li a');」と変数にしていたのを止めた(ヤメないと上手く作動しなかったので。その理由はワタクシの未熟ゆえ良く解らない…)。

サブナビ追加の縦型ナビ

HTML
<ul id="mainNavi">
    <li><a href="#">works</a>
        <ul class="sbNavi">
            <li><a href="#">web design</a></li>
            <li><a href="#">graphic design</a></li>
            <li><a href="#">goods</a></li>
            <li><a href="#">letter carving</a></li>
        </ul>
    </li>
    <li><a href="#">projects</a>
        <ul class="sbNavi">
            <li><a href="#">event calendar</a></li>
            <li><a href="#">letterpress map</a></li>
            <li><a href="#">line museum</a></li>
            <li><a href="#">moji shop</a></li>
            <li><a href="#">glossary</a></li>
            <li><a href="#">language & writing</a></li>
        </ul>
    </li>
    <li><a href="#">bibliography</a></li>
    <li><a href="#">contact</a></li>
    <li><a href="#">about</a></li>
</ul>

※URLは見やすさのために#に置き換えて省略。

サブナビ用CSSの追加
#mainNavi {
    width: 192px;
    text-transform: uppercase;
    border-bottom: dotted 1px #BAC3C9;
}
#mainNavi li {border-top: dotted 1px #BAC3C9;}
#mainNavi li a {
    display: block;
    padding: 0.8em 0.5em 0.5em;
}
.sbNavi {
 font-size: 11px;
 padding-left: 3em;
}
追加といっても見栄え調整用のみで、ナビの動作に関与するものではない。

jQuery
…は何もせず。今回のHTMLでのclass指定・id指定の場合、単純にサブナビを追加してもこのjQueryの動作が反映される、というのがもう1つのポイント。

完成、そしてデモの公開

こんな感じで、HOVERした以外の文字が薄くなり且つ背景色変更も加味された縦型ナビの完成。デモは以下のボタンから。