HTMLとCSSの位置づけ【DOMの基本操作】

2011/09/04

HTML

WEBシステム開発とは何かと問われた場合の最大公約数的答えは、多少くどい言い方にはなりますが、ブラウザからの要求をサーバー側で処理したHTMLを、ブラウザが受け取ってスクリプトを実行した結果をレンダリングしてWEBサイトという形で表示する過程を構築することになります。

ジャカルタ

インドネシアのITサービス

インターネット技術の急速な発展と普及により、優秀なIT人材を輩出することで知られるジャカルタのビヌス大学(BINUS)やバンドゥンのバンドゥン工科大学、インドネシアコンピューター大学(UNIKOM)の学生の多くがインターネット・WEB業界やソフトウェア業界を志望するようです。

続きを見る

HTMLの変遷に置いてかれた

僕は2000年にジャカルタからバリ島に引越し、会社立ち上げや家具・雑貨の輸出業務に伴う仕入れ・梱包等肉体労働で多くの時間を取られるあまり、WEBの技術変遷を追うことができない時期がありました。

ちょうどその時期に世間ではHTMLのバージョンアップが急激にブーストし、1999年のHTML4.01でHTMLは構造の定義に特化し、装飾はCSSに任せるという大きな方向転換がなされ、HTMLタグ自身に属性を書くという時代からスタイルシートの時代に入りました。

/*HTMLタグに属性を書く。フォントサイズの規定値3*/
<font size=5 color="red">

/*スタイルシートのfont属性を使う*/
<font style="font-size:12px; color:red;">

2001年には次世代のXHTML1.1が出されるともうわけわかめ状態で、文書型定義(Document Type Definition)が複数乱立し、しかも記述方法が長いという弊害が発生してきましたが、2014年に正式にW3Wの標準規格となったHTML5ではこのDTDの出だし部分が短いので済みます。

/*HTML 4.01 Transitional DTD*/
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">

/*XHTML1.1 */
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

/*HTML5*/
<!DOCTYPE html>
<html lang="ja">

DOCTYPEは「Strict(厳密な)」「Transitional(移行期)」「Frameset(フレームセット用)」の3種類ありまして、書き方によってブラウザは「互換モード」「標準準拠モード」に切り替わり、表示状態に差が出てきます。

ページ定義タグと構造化タグ

僕は1994年頃にWindows3.1搭載のIBM PCを購入して趣味のインド音楽のサイトを立ち上げたのですが、htmlとheadとbodyの3つは当時から既に存在するページ定義タグであり、全体をメタデータ部(HTMLドキュメント自身の情報)とコンテンツ部に分ける目的があります。headタグ内の情報はブラウザ上表示されません。


<html>
    |-<head></head>
    |-<body></body>
</html>

ページ定義タグで定義されたコンテンツ部に対してHTML5では構造化タグ(header, nav, article, aside, footer)でWEBサイト全体を「ヘッダー領域」「ナビゲーション領域」「コンテンツ領域」「サイドバー領域」「フッター領域」の5つに区切ってレイアウトします。


<body>
    |-<header></header>
    |-<nav></nav>
    |-<article></article>
    |-<aside></aside>
    |-<footer></footer>
</body>

コンテンツの意味のカタマリはdivタグにID属性やclass属性で定義するのが基本ですが、ヘッダーとかナビゲーションとかメジャーなヤツはHTML5のタグで標準装備してあげましょう、という趣旨です。

divタグのid属性とclass属性に対してCSSでレイアウト

で、ページタグと構造化タグで骨格を定義した後にはじめて、divタグでid属性とclass属性を定義しCSSを使ってレイアウトを整えていきます。

CSSは1999年頃にCSS2.1の仕様が確定してからCSS3にいたるまで機能が追加されるのみで仕様変更はないため、HTMLのようにバージョンによって表示が変わるということはありません。

id属性とclass名にネーミングルールはありませんが、一般的な作法として

  1. containerをbody直下に置いてheaderからfooterまでのコンテンツ全体を囲む
  2. wrapperでheaderやnavやasideを囲む

のように使われます。

html

body

container

header-wrapper

left

ブロック要素をまたなんでわざわざwrapperで囲むか?

WEBサイトのデザインで気をつけるべきことは「読みやすさ」と「見た目の良さ」だと思いますが、ブラウザ幅一杯に文字が広がっていると読みにくいし、かといって全体が両サイドから締め付けられると窮屈な印象を与えます。

このブログテーマもそうですが、最近のレスポンシブなテーマはほとんどと言っていいほどヘッダーにブラウザ幅一杯に背景画像を配置したり、キービジュアルをウィンドウの中央部に配置して見た目のインパクトを重視しています。

  1. 読みやすさ > 両サイドにスペース
  2. 見た目の良さ > 背景画像をブラウザ幅一杯に広げて開放する

header領域やnav領域をわざわざwrapperで囲みなおすのは、背景画像をブラウザ一杯に広げて開放感を出すためであり、このブログのヘッダー部分もそうしています。

犬たちまたサイトのウィジェット部分に最新のエントリーをサムネイル付きで表示して文字を右に回り込ませています。
これを実現するには画像のimgタグに「float:left;」を設定した後、親要素としてwrapperで囲って「overflow:hidden」でフロートの解除をしています。ちょうどこんな感じです。
<div id="wrapper-dog" style="border: 1px, solid, black; overflow:hidden;">
<img src="test_float.jpg" style="float:left; margin-right:10px;"/>
<p>ここにコンテンツ</p>
</div>

開発言語(タグ)の役割分担

タグ(要素)のプロパティ(属性)に値を持たせることでレイアウトを構成していき、なかでもid(ページ内で1個だけ)、 class(ページ内で複数可)、 styleの3つはグローバル属性と呼ばれます。

フレームワークやCMSなどは使わないクラシックなWEBシステム開発で登場する技術の役割分担は以下のようになります。

  1. HTML
    タグ(要素)単位でコンテンツに意味付けし、ブラウザのDOM(API)によりオブジェクト化され、JavaScriptから操作される。
  2. CSS
    HTMLの要素や属性をセレクタというオブジェクトとして扱い、プロパティに値をセットすることで装飾。
  3. PHP
    ブラウザから受け取った要求をサーバー側処理して結果をブラウザにhtmlとして返す。
  4. JavaScript
    ブラウザに内蔵されたスクリプト言語であり、イベントに応じて関数を実行したりDOMを通してWEBサイトの表示を変化させたりする。
  5. jQuery+jQuery Easy UI
    JavaScriptで頻繁に使う関数のライブラリで、セレクタのcssに値セット、サイト構築後に関数実行、エレメントの追加、オブジェクトのプロパティに値セットなどの機能がある。

HTMLのブロックレベル要素とインライン要素

HTML自体はプログラミング言語でなく文章に意味付けするマークアップ言語ですが、大雑把に分類すると以下のようになると思います。

  1. ページ定義タグ <html>, <head>, <body>
  2. HEADの中での情報付加やリンク <meta>, <title>, <link>, <style>
  3. BODYの中の構造化タグ <header>, <footer>, <nav>, <article>, <aside>,
    <section>
  4. セクション内 <p>, <hr>, <pre>, <blockquote>, <div>
  5. テキスト <strong>, <span>, <br>
  6. リスト <ol>, <ul>, <li>
  7. フォーム部品 <form>, <input>, <textarea>, <select>

タグ(要素)を見て一瞬それが何を意味するか判り難いものの例としてp(paragraph), hr(horizontal rule), pre(preformatted text), div(特に意味がある塊ではなくレイアウトや見た目を規定するためにCSSと一緒に使う), ol(ordered list), ul(unordered list), li(list item), span(特に意味があるわけではなくテキストの一部になんらかのスタイルを施す場合)でしょうか。

これらのタグに属性(プロパティ)と値を持たせることで付属情報を持たせることになります。例えば<head>タグ内で使うタグの属性を総動員すると・・・

<meta charset="utf8">
<meta name="description" content="インドネシア生活ブログです。">
<title>嗚呼インドネシア</title>
<link rel="shortcut icon" href="favicon.ico">
<style>
        body { background: #dda0dd; }
</style>
//または・・・
<link rel="stylesheet" href="style.css">

また属性の中でも id(ページ内で1個だけ), class(ページ内で複数可), styleの3つはグローバル属性と呼ばれます。

HTML5の特徴

本来のHTMLの目的は文書の構造を表すことですが、HTML自体がアプリケーションとしての意味を持つようになったため、タグは要素の開始と終了を表す以外に、システムから見て意味があるカタマリをより明快に表現できるようになりました。

追加されたタグ

例えばこれまでヘッダー部分をあらわすのにID属性で「div id="header"」と指定していたのが、独立した「header」タグでより明快に表現できるようになりました。

  1. 構造化タグ
    header
    footer
    aside
    section
    article :内容が単体で完結するセクション
    menu
  2. 取得先の意味
    figure:画像
    embed:埋め込み
    time:日時

取得先の意味を表すタグは、他のアプリケーションや検索エンジンのクローラーなどのシステムに対して、理解してもらうという「意味付け」という意味しかもちません。

timeタグ

システムに対してdatetime属性にYYYY-MM-DDやHH:MMのようなフォーマットで意味を伝えることができます。

<time datetime="2016-01-01">2016年1月1日 12:00</time>

CSS上でのタグと属性の指定方法

id属性の値は「#」、class属性の値は「.(ピリオド)」で定義します。リンクタグ「a」に対するマウスオーバーとかの擬似クラスには「a:hover」みたいに「タグ+コロン+スタイル」で定義します。

このようにHTMLタグ(要素)や属性をCSS上でセレクタというオブジェクトとして扱いプロパティに値を設定します。

//header
#header {
	width: 100%;
}
#header-inner {
	width: 800px;
	margin: 0 auto;
}
#header-top {
	height: 80px;
	font-size:1.1em;
}
/*header-topブロック領域内のheadlineクラス属性*/
#header-top .headline {
	float: right;
}

/*header-topブロック領域内のh1, h2, h3見出しタグ*/
#header-top h1,h2,h3 {
	padding-top: 12px;
}
/*header-topブロック領域内の段落タグ*/
#header-top p {
	padding-top: 5px;
}

タグの記述パターンは「スペース区切りが継承、カンマ区切りが列挙」です。

/*タグ(セレクタ)複数指定(カンマ区切り)*/
main, article, aside, header, footer {
	display: block;
}

/*タグ内のクラス(ピリオド)*/
body.mceContentBody {
	background-color:#fff;
}

/*リンクタグ領域内の画像のマウスオーバー(スペース区切)*/
a:hover img {
	-moz-opacity: 0.8; opacity: 0.8;
}

/*画像タグ内のクラス複数指定(カンマ区切り)*/
img.size-full, img.size-large {
	margin-bottom: 10px;
}

/*タグ指定領域のクラス指定領域のリンク(スペース区切)*/
header .sitename a{
	font-size: 22px;
}

レイアウト

スタイルシートでとまどうのは主にレイアウト定義の部分だと思います。HTMLタグにはdivやpなど下に積み重なっていくブロックレベル要素が確保するブロックボックスとspanやaなど左につめられて配置されるインラインレベル要素が確保するインラインボックスがあります。

HTMLタグで囲まれた要素(内容)は四角い領域を確保するというのがボックスモデルというCSSの基本的な考えで、具体的には要素を囲んだタグに対して「width, height, padding, margin, border」プロパティを指定し「px, em, %」の値を与えることです。

displayプロパティ

displayプロパティではHTMLデフォルトの要素のレイアウトを恣意的に変更することができます。

display : block;
display : inline;
display : none;

floatプロパティ

//bodyタグ内の左カラム
#left{
    float : left;
    width : 30%;
}
//bodyタグ内の右カラム
#right{
    float : right;
    width : 70%;
}

img{
      /*左寄せで右に文字を回りこませる*/
      float:left;
      /*時計周りに上10右20下30左40*/
      margin:10px 20px 30px 40px ;
}

paddingとmarginについては4つまとめて指定すれば時計回りに読みますが、それ以外の指定の場合は以下の意味になります。

  1. 1つ:all
  2. 2つ:top/bottom, right/left
  3. 3つ:top, right/left, bottom
  4. 4つ:top, right, bottom, left

marginが隣同士になる場合には小さいほうが相殺され、大きいほうが優先されます。

backgroundプロパティ

背景画像の配置ではurl・position・repeatを指定します。

blockquote{
      background-image: url(images/quote.png);
      background-position: left 5px top 5px;
      background-repeat: no-repeat;
}

potisionプロパティ

またブロックレベル要素やインラインレベル要素ののデフォルトの基準値であるstatic(左上)を変更できるのがpositionプロパティで、値をrelative(相対的)に変更の上、top, bottom, left, rightはpositionで決めた配置からの位置を決めるプロパティです。

<div id='parent'><div id='child'>子ブロック</div></div>

<style>
#parent{
    width : 400px;
    height :200px;
    background : #7fffd4;
    position : relative;
    top : 20px;
    left : 50px;
}
#child{
    width : 50%;
    height :50%;
    background : yellow;
    position : relative;
    top : 20px;
    left : 50px;
</style>

pxはピクセル(画面1つ1つの点)で絶対指定、emと%は親要素の値に対しての比率なので相対指定になりますが、注意するのはwidthの%指定は無条件OKですが、heightの場合は親要素のheightの%を明示的に示す必要があることです。

親ブロック

子ブロック




簡単に言うとrelativeはOriginal position(staticの状態で居るべき位置)からの位置、absoluteは親要素を基点とした位置を表します。

positionプロパティは通常この組み合わせでしか使用しません。

JavaScriptのwindowオブジェクトとdocumentオブジェクト

JavaScriptのDOMを操作するためのオブジェクトは階層構造で管理されており、その最上位にあるオブジェクトがwindowオブジェクトであり、JavaScriptが起動するタイミングで自動的に生成されます。

JavaScriptのwindowオブジェクトとdocumentオブジェクトの関係ですが、ドキュメントを表示するウィンドウに対応するのがWindowオブジェクトで、HTMLドキュメントに対応するのが documentオブジェクトになります。

Javascript

PHP・JavaScript・VBの書き方の比較整理

プログラムのコードは変数、値(リテラル)、式、制御文の4つから構成され、制御文の書き方には順次処理、分岐処理、繰り返し処理の3種類があります。

続きを見る

例えばダイアログボックスを表示するのはWindowオブジェクトの機能(メソッド)であるwindow.alert("ダイアログメッセージ");で行ないますが、HTMLページ中に文字を出力させるにはdocument.write("テキスト");で行ないます。

DOMにより生成されるエレメントオブジェクト

サーバーから送られるHTMLをブラウザが描画(rendering)してWEBサイトが見られるわけですが、ブラウザがHTMLのタグに対応するオブジェクトを生成する機能がDOM(Document Object Model)であり、ブラウザのDOMはJavaScriptに操作してもらうために存在するとも言えます。

<html>
  <head>
    <title>Launch IT at JKT</title>
  </head>

  <body>
    <div>ブロック1</div>
    <div>ブロック2</div>
  </body>
</html>

<html>~</html>がdocumentオブジェクトであり、そのプロパティとして<body>~</body>がありdocument.bodyでアクセスします。

そしてbody内のタグにはDOMの機能によって対応するエレメントオブジェクトが生成されます。

エレメントの参照

DOMはNodeインターフェイスというツリー構造のインターフェイスを装備しており、JavaScriptはNodeを通じてDOMにアクセスします。Nodeインターフェイスの最上位がhtml要素から生成されるdocumentオブジェクトです。

HTMLタグはDOMによりオブジェクト化されていますがこれらをエレメントと呼び、getElementByIdやgetElementsByName(引数のnameのDOMオブジェクトを配列を返す)のようにid属性やname属性を指定することでエレメントのオブジェクトにアクセスします。

<html>
  <head>
    <script type="text/javascript">
      function show(){
        var txt = document.getElementById("txt1");
        txt.innerHTML = "やま";
      }

      function doKlik(){
        var txt2 = document.getElementById("txt2");
        var rd = document.getElementsByName("rad");
        for(i=0; i<rd.length; i++){
          var rd_array=rd[i];
          if(rd_array.checked){
            alert(txt2+rd_array.value);
          }
        }
        alert(txt2);
      }
    </script>
  </head>

  <body onload="show();">
    <div id="txt1"></div>

    <form onsubmit="return false;">
      <input type="text" id="txt2">
      <input type="radio" id="rd1" name="rad" value="male">
      <input type="radio" id="rd2" name="rad" value="female">
      <input type="button" onClick="doKlik();" value="Click">
    </form>

  </body>
</html>

エレメントの更新

HTMLタグの場合、style属性を定義することで表示を変化させますが、エレメントオブジェクトのstyleプロパティを変更することで、関数からこれを実行することができます。

getElementByIdメソッドで該当エレメントへの参照を取得し、styleプロパティを変更します。ちなみにプロパティは資産とか土地とか所有物という意味でオブジェクトの所有物を表します。

<html>
  <head>
    <script type="text/javascript">
      function doklik(){
        var txt=document.getElementById("back");
        txt.style.background="#999";
        
      }
    </script>
  </head>
  <body>
    <div id="back">Backgoround</div>
    <input type="button" onClick="doklik();" value="OK">

  </body>
</html>

エレメントの追加

createElementメソッドで空のdivエレメントオブジェクトを作成して、innerHTMLメソッドで空のdivエレメントに表示する数字を設定して、appendChildメソッドで作成したエレメントをHTML中のid属性countの場所に表示します。

<html>
  <head>
    <script type="text/javascript">
      var cnt=1;
      function doKlik(){
        //divエレメントオブジェクトの作成
        var obj=document.createElement("div");

        //表示する数字を設定
        obj.innerHTML=cnt;
        cnt++;
        
        //作成したdivエレメントにappendChildにてobjオブジェクトを組み込むことで表示される。
        var num=document.getElementById("count");
        num.appendChild("obj");
        
      }
    </script>
  </head>

  <body>
    <div id="count"></div>
    <input type="button" onclick="doKlik();" value="OK">

  </body>

</html>

エレメントの削除

getElementIdで該当idエレメントへの参照を取得し、lastChildプロパティで最後の子要素を取得し、removeChildメソッドで該当エレメントを削除します。

<html>
  <head>
    <script type="text/javascript">
      function doRemove(){        
        //親要素countへの参照を取得
        var num=document.getElementById("count");

        //lastChildプロパティで最後の子要素を取得
        var obj=num.lastChild("obj");
        if(obj){
            //子要素が存在する場合、該当要素を文章から削除
            removeChild(obj);
        }
      }
    </script>
  </head>
 
  <body>
    <div id="count"></div>
    <input type="button" onclick="doRemove();" value="Remove">
 
  </body>
 
</html>

ファントム品

製造業の生産管理部門では、内示や確定オーダを元に、部品構成表(BOM)から所要量展開を行うことで、購買指図と製造指図を発行しますが、BOMに登録する品目は、入荷実績または製造実績により通常は在庫管理されます。

ただし「工程途中で跳ね出される中間品で、在庫があるものは所要量展開時に引き当てをしたいが、新規に製造指図は発行したくない」という素性の怪しい品目を、ファントム(怪人)品と呼びます。ファントム品

セット品やキット品など、その品目自体の在庫管理はしないが、個々の部品単位で管理する、という性格の品目もファントム品です。

オペラ座の怪人(Phantom of the Opera)という有名なミュージカルがありますが、この怪しいファントム品はMRP計算のための製造リードタイムは0日に設定しておいて、製造指図も出ないので実績も入れる必要ありません。

クラス(部品)とインターフェイス(ファントム品)

MRP計算により製造指図を生成する部品(例えばクランクシャフト)は、部品自体の属性(寸法・重量など)や用途(ピストン運動を回転運動に変換する)をひっくるめて「CRANK_SHAFT001」という品目コードを定義します。

これは構造体(属性)に関数(用途)を加えてカプセル化(品目コード)したものと言えるかもしれません。

このようにクランクシャフトという部品クラスは、構造体の中に目的を果たす機能を完備していますが、熱処理後に跳ね出されたペンディング品(ファントム品)には、属性も用途も定義されていないにもかかわらず、品目コードとしては存在しています。

言い換えるとクランクシャフトクラスは、クランクシャフトにインスタンス化できますが、用途のないペンディング品はそのままではインスタンス化できないため、前工程のショットブラスト工程上がり品(サブクラス)をオーバーライドします。ファントム品

ファントム品は自身が、インスタンス化できない抽象クラス(abstract)であり、インスタンス化できない抽象的なクラスをインターフェイスと言います。

DOMオブジェクトが提供するNodeインターフェイス

ブラウザはHTMLの開始タグから終了タグまでを、1つのDOM(Document Object Model)オブジェクトとして要素化(エレメント化)し、DOMはJavaScriptやjQueryからエレメントにアクセスするために、Nodeインターフェイスを提供します。

インターフェイスという言葉は2つの特徴を持っています。

  1. 異なる媒体(JavaScriptとDOM)を繋ぐもの(API)
  2. それ自体をインスタンス化することに意味がないクラス