"BOKU"のITな日常

BOKUが勉強したり、考えたことを頭の整理を兼ねてまとめてます。

rowspanが他の列にも影響する謎動作?「vertical-align: baseline;」指定と「textarea」の罠について。

f:id:arakan_no_boku:20210801224839p:plain

目次

 rowspan指定が他に影響してしまう謎動作

どういうことが起きたか?を簡単に書きます。

rowspan="5"の2つの列の間に、rowspan指定をしない行を挟み込むようなテーブルがあったと思ってください。。

f:id:arakan_no_boku:20210801231004p:plain

HTMLはこんな感じです。

実際はもっと複雑ですけど、説明用にごく単純なものにしています。

<html>
	<head>
		<link rel="stylesheet" type="text/css" href="./my.css" media="all" />
	</head>
	<body>
		<table style="border: solid 1px">
			<tbody>
				<tr>
					<th>A</th>
					<th>B</th>
					<th valign="middle">C</th>
				</tr>
				<tr>
					<td rowspan="5" valign="middle">5行にまたがる</td>
					<td valign="middle">1行ずつ表示したい★★★★★★★</td>
					<td rowspan="5" style="height: 100px">
						<textarea style="width: 100%; height: 100%"> TEXTAREAを表示</textarea>
					</td>
				</tr>
				<tr>
					<td valign="middle">2行目。</td>
				</tr>
				<tr>
					<td valign="middle" class="">3行目</td>
				</tr>
				<tr>
					<td valign="middle" class="">4行目</td>
				</tr>
				<tr>
					<td valign="middle" class="">5行目</td>
				</tr>
			</tbody>
		</table>
	</body>
</html>

ここで読み込んでいるCSS(my.css)も、テーブル要素のごく簡単な設定をしているだけです。

table, tbody, tfoot, thead, tr, th, td {
	margin: 3px;
	padding: 3px;
	border: solid 1px;
}

普通に考えて、おかしくなる要素はありません。

ある日突然レイアウトが崩れた?!

それなのに・・です。

いきなり、こんな風にレイアウトが崩れて表示するようになりました。

f:id:arakan_no_boku:20210801231304p:plain

HTMLは変更していません。

見たところ、 rowspan="5" しているTDタグの「valign="middle"」の指定がきかなくなっているだけでなく、A列、C列のrowspanが他の列(B列)の1行目にだけ影響してしまっているように見えます。

しかも。

奇妙なことに、C列から<textarea>を除くと、もとに戻るのです。

f:id:arakan_no_boku:20210801233341p:plain

最初にこの現象を見たときは、正直、途方にくれました。

vertical-align: baseline;指定のせいだった

実際は上記のような単純なHTMLでもCSSでもなく、全部で数千行くらいあるものだったので、原因を見つけるのに時間は相当かかったのですけど・・。

なんとか原因をつきとめることはできました。

いつもながら、わかってしまえば、原因は単純です。

誰かが「my.css」の定義の一部を以下のように修正していたのです。

table, tbody, tfoot, thead, tr, th, td {
	margin: 3px;
	padding: 3px;
	border: solid 1px;
	vertical-align: baseline;
}

そう。 

table関連要素の共通設定に

vertical-align: baseline;

が追加されていたのです。

これは、要素のベースラインを親要素のベースラインに揃えるというものなので、table関連のような階層関係(まあ、親子関係といえなくもない)のものに指定すると、一見よさげに見えるのですけれど・・実は落とし穴がありました。

こちらに、そのあたりが、さらっと書いてあります。  

developer.mozilla.org

引用すると。

baseline
要素のベースラインを親要素のベースラインに揃えます。 <textarea> のような、一部の 置換要素 のベースラインは HTML 仕様で未定義であり、このため、このキーワードの挙動はブラウザにより異なるかもしれません。

ということです。

つまり、vertical-align: baseline;の指定をしたTDタグ内とかに、<textarea>のように「ベースラインがHTML仕様で未定義」な要素を置くと、何がおきても知らないよ・・というわけです。

まさしく、今回おきたこと・・まんまじゃないですか。

教訓:vertical-align: baseline;を安易に使わない

今回の問題は、vertical-align: baseline;の記述をCSSから消したらおさまりました。

なのですけど。

普通に使ってて問題なさげに見えても、<textarea>を配置したとたんに、周囲が崩れていく・・という挙動はやばすぎますよね。

時限爆弾みたいなものです。

しかも、今回、たまたま<table>の<td>タグでしたが、たぶん<div>とかでも起こりえる話なので、ネストしたDIVタグで複雑なレイアウトなんか組んでた日には、何がおきるのかなんて、たぶん誰にもわかりません。

今回のように、<textarea>の配置された箇所ではなく、隣の要素が崩れたりすると、原因がどこにあるのかの当たりをつけるだけでも、なかなか大変な作業になります。

絶対、避けるべし!!

自分はそう思い知りました。

だから、教訓です。

共通利用のCSSで「vertical-align: baseline;」は使わないように徹底すべし!!

どうしても使いたいなら、ヤバさをちゃんと認識したうえで、<textarea>禁止にするか、局所的なStyleで使うようにするとか・・したほうがいいみたいです。

ではでは。