WordPressでInDesignの様な文字組−その⑦

簡易的な 役物詰めを行います 前回のぶら下がり処理を応用し 出来るだけコンパクトな設定で実装します

コンパクト ゆえ 簡易的になります

スポンサーリンク

役物詰めとは

基本的に 日本語のフォントは縦横が同サイズの正方形です それは役物 括弧 かっこ や句読点や中点 も同様で 正方形の中に字形とアキ 空白 が共存しています

よって 役物が表示される際は適度なアキが あらかじ め確保されているため 可読性が高くなります

すべて全角幅
すべて全角幅

しかし 役物が連続するとアキも連続してしまうため 文字間が必要以上に開き 間延 まの びした文章になってしまいます

役物間のアキを調整
役物間のアキを調整
更に詰めてみる
更に詰めてみる

こういった連続する役物や 行頭行末に表示される役物のアキを調整することを役物詰めといいます

役物詰めを行うことにより 文字間のアキが引き締まり可読性が高まりますが 詰めすぎると かえ って読み づら くなる場合もあります

この辺りは執筆者の好みや 出版社のルール ハウスルール? ってくると思われます

詰め方

ネガティブマージン

真っ先に思いつくのはネガティブマージンでしょうか 例えばこんな感じ

html

 <p> 
	 <span class="thx_opening_bracket"> </span> 
	寿司  
	 <span class="thx_closing_bracket"> </span> 
	 <span class="thx_mid_dot"></span> 
	 <span class="thx_opening_bracket"> </span> 
	  将棋
	 <span class="thx_closing_bracket"> </span> 
 </p> 

css

 .thx_closing_bracket + .thx_mid_dot { 
	 margin-left: -0.5em; 
 } 

 .thx_mid_dot + .thx_opening_bracket { 
	 margin-left: -0.5em; 
 } 

これはダメです このままではダメです 理由は二つあります

このままではダメ

理由その壱

css の記述が ふく らんでしまいます 仮に 約物の種類を 開き括弧閉じ括弧句読点中点 の4つとした場合 その組み合わせは 4x4=16 通りの記述が必要になります

まぁ それでも 16 通りならそれほどは多くないので許容範囲内ですが 次の理由が重要です

理由その弐

行頭行末の判定ができません 文章頭ならまだなんとかなりますが 行頭行末は表示される環境に拠って異なるため jQuery での処理などが必要になります

では どうするか 行頭行末のアキをどの様に調整するか そうです アレです

半角スペースです

半角スペースで調整

前回の処理と同様に それ以外 を正規表現で検索置換する際に半角スペースを付与します 先程の例題の場合 この様になります

html

 <p> 
	 <span class="thx_clps_spc"> </span> 
	 <span class="thx_opening_bracket"> </span> 
	 <span class="thx_fwid"> 寿司 ○</span> 
	 <span class="thx_closing_bracket"> </span> 
	 <span class="thx_clps_spc"> </span> 
	 <span class="thx_clps_spc"> </span> 
	 <span class="thx_mid_dot"></span> 
	 <span class="thx_clps_spc"> </span> 
	 <span class="thx_clps_spc"> </span> 
	 <span class="thx_opening_bracket"> </span> 
	 <span class="thx_fwid">○ 将棋 </span> 
	 <span class="thx_closing_bracket"> </span> 
	 <span class="thx_clps_spc"> </span> 
 </p> 

こうする事で 行頭行末の半角スペースは勝手に吸収されます

連続する半角スペースは単一の半角スペースで表示されるため 必要以上にアキが生じません

他には新たに .thx_fwid が登場していますが これは css で調整を行う際 隣接指定の + が正しく挙動する様に付加してあります

あとは css で役物に対して font-feature-settings: "halt"; と半角幅を指定し 中黒のみ前後に半角スペースが発生しているため微調整をして完成です

ちなみに この半角スペースのクラス名 thx_clps_spc この挙動がマージンの相殺 そうさい Collapsing Margins に似ている事から命名しています

css

 /*  全角化  */ 
 .thx_fwid { 
	 font-feature-settings: "fwid"; 
 } 

 /*  相殺スペース  */ 
 .thx_clps_spc { 
	 -webkit-user-select: none; 
	 user-select: none; 
 } 

 .chrome .thx_clps_spc { 
	 font-family: sans-serif; 
	 font-feature-settings: "hwid"; 
 } 

 .gecko .thx_clps_spc { 
	 font-family: Kosugi; 
	 line-height: 0; 
 } 

 .safari .thx_clps_spc { 
	 font-family: Kosugi; 
	 line-height: 0; 
 } 

 /*  括弧  */ 
 .thx_opening_bracket, 
 .thx_closing_bracket { 
	 font-feature-settings: "halt"; 
 } 

 /*  中黒  */ 
 .thx_mid_dot { 
	 font-feature-settings: "halt"; 
 } 

 .thx_clps_spc + .thx_mid_dot { 
	 margin-left: -0.25em; 
 } 

 .thx_mid_dot + .thx_clps_spc { 
	 margin-left: -0.25em; 
 } 

カスタマイズ方法

前回の ぶら下がり 及び元となった 和欧間スペース 機能を含めたソースコードになります

check
  • カスタマイズは自己責任でお願いします。
  • wp-cocoon.comサイトのサポート対象外となります。

php

 //html をテキストとタグに分解
 function html_split_text_tag( $html ) { 
	 //alt 内の > を文字参照に
	 if ( preg_match_all( '{alt="[^\"]*>}uis', $html, $match ) ) { 
		 foreach ( $match as $value ) { 
			 $alt_amp = preg_replace( '{(>)}is', '&gt;', $value ); 
			 $html    = str_replace( $value, $alt_amp, $html ); 
		 } 
	 } 

	 //html をテキストとタグに分解ペアリング
	 $tag_match = '{(<.*?>)}uis'; 
	 $pairing   = array_chunk( 
		 preg_split( 
			 $tag_match, 
			 $html, 
			 -1, 
			 PREG_SPLIT_DELIM_CAPTURE 
		 ), 
		 2 
	 ); 

	 // ペア補充 notice 対策 
	 $count                 = count( $pairing ); 
	 $pairing[ $count - 1 ] = array( ' ', ' ' ); 

	 return $pairing; 
 }//html_split_text_tag( $html ) 
 // 半角スペース用に Kosugi をエンキュー
 function enqueue_kosugi_space() { 
	 wp_enqueue_style( 'google-webfont-style', '//fonts.googleapis.com/css?family=Kosugi&text= ' ); 
 } 

 add_action( 'wp_enqueue_scripts', 'enqueue_kosugi_space' ); 
 // 簡易的な日本語組版
 function thx_typesetting( $the_content ) { 
	 //html をテキストとタグに分解
	 $pairing = html_split_text_tag( $the_content ); 

	 // ペアリングを span しながら結合
	 $the_content = ''; 
	 foreach ( $pairing as $value ) { 
		 $str = trim( $value[0] ); 
		 $tag = $value[1]; 

		 if ( 
			 ( '</style>' === $tag ) 
			 || 
			 ( '</rt>' === $tag ) 
			 || 
			 ( '</li>' === $tag ) 
		 ) { 
			 $the_content .= $str; 
		 } else { 
			 $the_content 
			 .= preg_replace_callback_array( 
				 [ 
					 // 欧文の検索
					 '#' . 
						 '[ !-;=-~\p{Ll}]+' . 
					 '#uis' => function ( $match ) { 
						 return 
							 '<span class = "thx_wao_spc"> </span>' . 
							 '<span class = "thx_pwid">' . 
								 $match[0] . 
							 '</span>' . 
							 '<span class = "thx_wao_spc"> </span>'; 
					 }, 
					 // 句読点の検索
					 '#' . 
						 '[、。, ]' . 
					 '#uis' => function ( $match ) { 
						 return 
							 '<span class = "thx_punc_wrap">' . 
								 '<span class = "thx_punctuation">' . 
									 $match[0] . 
								 '</span>' . 
							 '</span>' . 
							 '<span class = "thx_clps_spc"> </span>'; 
					 }, 
					 // 中点の検索
					 '#' . 
						 '[ ・:; ]' . 
					 '#uis' => function ( $match ) { 
						 return 
							 '<span class = "thx_clps_spc"> </span>' . 
							 '<span class = "thx_mid_dot">' . 
								 $match[0] . 
							 '</span>' . 
							 '<span class = "thx_clps_spc"> </span>'; 
					 }, 
					 // 括弧の検索
					 '#' . 
						 '[ ({[〔「『【〈《]' . 
					 '#uis' => function ( $match ) { 
						 return 
							 '<span class = "thx_clps_spc"> </span>' . 
							 '<span class = "thx_opening_bracket">' . 
								 $match[0] . 
							 '</span>'; 
					 }, 
					 '#' . 
						 '[)}]〕」』】〉》 ]' . 
					 '#uis' => function ( $match ) { 
						 return 
							 '<span class = "thx_closing_bracket">' . 
								 $match[0] . 
							 '</span>'; 
							 '<span class = "thx_clps_spc"> </span>' . 
					 }, 
					 // 欧文と役物以外を全角処理に
					 '#' . 
						 '[^ !-~\p{Ll}、。, ・:; ({[〔「『【〈《)}]〕」』】〉》 ]+' . 
					 '#uis' => function ( $match ) { 
						 return '<span class = "thx_fwid">' . $match[0] . '</span>'; 
					 }, 
				 ], 
				 $str 
			 );//$the_content .= preg_replace_callback_array() 
		 }//else ( '</style>' === $tag ) 
		 $the_content .= $tag; 
	 }//foreach ( $pairing as $value ) 
	 return $the_content; 
 }//thx_typesetting( $the_content ) 
 add_filter( 'the_content', 'thx_typesetting', 21000 ); 
 add_filter( 'the_category_content', 'thx_typesetting', 21000 ); 

css

 /*  禁則処理と両端揃え */ 
 body { 
	 line-break: strict; 
	 text-align: justify; 
 } 

 /*  全角化  */ 
 .thx_fwid { 
	 font-feature-settings: "fwid"; 
 } 

 /*  プロポーショナル化  */ 
 .thx_pwid { 
	 font-feature-settings: "pwid"; 
 } 

 /*  和欧間スペース  */ 
 .thx_wao_spc { 
	 font-family: Kosugi; 
	 font-size: 0.5em; 
	 line-height: 0; 
	 -webkit-user-select: none; 
	 user-select: none; 
 } 

 code .thx_wao_spc { 
	 display: none; 
 } 

 /*  相殺スペース  */ 
 .thx_clps_spc { 
	 -webkit-user-select: none; 
	 user-select: none; 
 } 

 .chrome .thx_clps_spc { 
	 font-family: sans-serif; 
	 font-feature-settings: "hwid"; 
 } 

 .gecko .thx_clps_spc { 
	 font-family: Kosugi; 
	 line-height: 0; 
 } 

 .safari .thx_clps_spc { 
	 font-family: Kosugi; 
	 line-height: 0; 
 } 

 code .thx_clps_spc { 
	 display: none; 
 } 

 /*  句読点  */ 
 :not(code)>.thx_clps_spc + .thx_punc_wrap { 
	 margin-left: -0.5em; 
 } 

 .thx_punc_wrap { 
	 position: relative; 
	 display: inline-block; 
 } 

 .chrome .thx_punc_wrap + .thx_clps_spc { 
	 font-feature-settings: "fwid"; 
 } 

 .gecko .thx_punc_wrap + .thx_clps_spc { 
	 font-size: 2em; 
 } 

 .safari .thx_punc_wrap + .thx_clps_spc { 
	 font-size: 2em; 
 } 

 .thx_punctuation { 
	 position: absolute; 
	 font-feature-settings: "halt"; 
	 line-height: 1em; 
 } 

 code .thx_punc_wrap .thx_punctuation { 
	 position: relative; 
	 font-feature-settings: "fwid"; 
	 bottom: initial; 
 } 

 .chrome .thx_punctuation { 
	 bottom: -0.1em; 
 } 

 .gecko .thx_punctuation { 
	 bottom: -0.15em; 
 } 

 .safari .thx_punctuation { 
	 bottom: -0.15em; 
 } 

 /*  中黒  */ 
 :not(code)>.thx_mid_dot { 
	 font-feature-settings: "halt"; 
 } 

 :not(code)>.thx_clps_spc + .thx_mid_dot { 
	 margin-left: -0.25em; 
 } 

 :not(code)>.thx_mid_dot + .thx_clps_spc { 
	 margin-left: -0.25em; 
 } 

 /*  括弧  */ 
 :not(code)>.thx_opening_bracket, 
 :not(code)>.thx_closing_bracket { 
	 font-feature-settings: "halt"; 
 } 

まとめ

簡易さ故の問題点

半角スペースを利用することにより 役物へのスタイル指定を大きく減らす事が可能になりますが 問題点もあります

例えば コレ 、、、」

連続する句読点を詰めるために css

 :not(code)>.thx_clps_spc + .thx_punc_wrap { 
	 margin-left: -0.5em; 
 } 

としていますが 改行位置によってはこの様になってしまいます

行頭の句読点
行頭の句読点

また他にも 半角スペース ゆえ の問題点もあります

半角スペースは改行可能な位置であるため 括弧などが連続した場合に禁則処理が効かなくなってしまいます

半角スペースで改行
半角スペースで改行

役物を詰めるためとは言え 禁則処理が効かなくなってしまうのは美しくないので もう少し煮詰 につ めます 長くなりましたので 今回はココまで

次回 詰むや 詰まざるや

コメント