愚者の経験

「また今度」はほとんどこない

カテゴリーアーカイブ: HTML

[CSS]ボックスの高さをページにあわせるには?

よくhtmlとbodyにheight:100%;つけて、中のボックスにmin-height:100%;をつければ~的なのがあるんですが
height:100%;ボックスの上下に別の高さを持つ要素があれば、その分の高さ+ページの高さになってしまいます…(´・ω・`)

height:100%;は親要素の高さをそのまま持つという意味ですから当たり前なのですがどちらかと言うと
「(途中から始まったとしても)画面下まで一杯の高さを持ちたい」という要望が多いと思うのです。

これをする場合はまず親要素(bodyとかのページそのものの高さを持つもの)にposition:absolute;
途中に囲むdivなどにはheight:100%;だけを指定して、下まで伸ばすボックス要素にposition:absolute;を追加、
座標起点がページ左上になるのでボックスの上にある要素の高さXXを合計してborder-top:XX solid #fff;box-sizing:border-box;height:100%;
で、下まで伸ばすためにbottom:0;を利用する

でごり押してるんですがもっといい方法ありませんかね?

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>ハイト100%</title>
        <style type="text/css">
            html{height: 100%;}
            body{height: 100%;margin: 0;position: absolute;}
            #main{height: 100%;width: 800px;position: absolute;}
            #main>#tab {height: 100%;box-sizing: border-box;border-top: 70px #fff solid;}
            
            header{margin: 10px;height: 50px;position: absolute;}
            .tabradio{display: none;}
            #contents{width: 800px;display: table;height:100%;}
                        
            #sono1lbl{background: #ffbf7f;}
            #sono1_cont{border-color: #ffbf7f;}
            #sono2lbl{background: #ffff7f;}
            #sono2_cont{border-color: #ffff7f;}
            #sono3lbl{background: #7fff7f;}
            #sono3_cont{border-color: #7fff7f;}
            #sono4lbl{background: #7fbfff;}
            #sono4_cont{border-color: #7fbfff;}
            #sono5lbl{background: #ff7fff;}
            #sono5_cont{border-color: #ff7fff;}
                        
            .tabpage{display: none;position:absolute;top: 150px;left:0;bottom: 0;right: 0;width: 120%;box-sizing:border-box;border-width: 3px;border-style:solid;font-size: 20px;}
            #sono1:checked+#sono1_cont{display:block;}
            #sono2:checked+#sono2_cont{display:block;}
            #sono3:checked+#sono3_cont{display:block;}
            #sono4:checked+#sono4_cont{display:block;}
            #sono5:checked+#sono5_cont{display:block;}
            
            #tab{width: 100%;font-size:0;height:100%;}
            .tabindex{display:inline-block;font-size:20px; width: 20%;height: 80px;text-align: center;border:#a5a5a5 1px solid;box-sizing:border-box;padding-top:25px;}
        </style>
    </head>
    <body>
        <div id="main">
            <header>
                <h1>ハイト100%テスト</h1>
            </header>
            <div id="tab">
                <label id="sono1lbl" for="sono1" class="tabindex">その1</label>
                <input id="sono1" type="radio" name="nav" class="tabradio" checked>
                <div id="sono1_cont" class="tabpage">その1</div>
                <label id="sono2lbl" for="sono2" class="tabindex">その2</label>
                <input id="sono2" type="radio" name="nav" class="tabradio">
                <div id="sono2_cont" class="tabpage">その2</div>
                <label id="sono3lbl" for="sono3" class="tabindex">その3</label>
                <input id="sono3" type="radio" name="nav" class="tabradio">
                <div id="sono3_cont" class="tabpage">その3</div>
                <label id="sono4lbl" for="sono4" class="tabindex">その4</label>
                <input id="sono4" type="radio" name="nav" class="tabradio">
                <div id="sono4_cont" class="tabpage">その4</div>
                <label id="sono5lbl" for="sono5" class="tabindex">その5</label>
                <input id="sono5" type="radio" name="nav" class="tabradio">
                <div id="sono5_cont" class="tabpage">その5</div>
             </div>
        </div>
    </body>
</html>

liをdisplay:inline-blockで並べた時の隙間

リストを横に並べるときに「display:inline-block」を使うと
隙間が出来ます。これはHTMLソース側でとの間に改行、タブ文字がある場合に空白として認識されるためなのだそうですが…

ul
{
list-style-type:none;
margin:0;
padding:0;
}
li
{
background-color:#ff9;
display:inline-block;
margin:0;
padding:0;
}
<ul>
<li>HOME</li>
<li>MENU</li>
<li>TOPPING</li>
<li>LINK</li>
</ul>

このように空白ができます。デザインする場合あんまりよくありませんね。
解決方法はいろいろあるみたいです。
・リストで改行を入れずにつなげて書く。

の間をコメントアウト()する。
・「display:inline-block」でなく「float:left」にする。
・「margin」を調整する。
・「letter-spacing」を調整する。
しかし簡単さでいうと親要素(つまりul)に「font-size:0;」を指定するが一番いいと思います。

ul
{
list-style-type:none;
font-size:0;
margin:0;
padding:0;
}
li
{
background-color:#ff9;
display:inline-block;
margin:0;
padding:0;
}

<ul>
<li>HOME</li>
<li>MENU</li>
<li>TOPPING</li>
<li>LINK</li>
</ul>

CSSで折り返しても線を引く方法 2

前回の続きで「折り返した後にも線を引く方法」ですが、ずばり

『コンテンツ(divタグ)一つ一つがwidthを無視した長い線を上に持てばいい』と気づきました。
それぞれのdivの「border-top」がかなり長いようなイメージです。

折り返す前はtop位置がそろえて1本の線に見せます。
折り返した後でもそれぞれの線で区切って見えるというわけです。

前々回の投稿で紹介したdivタグを「display:inline-block」で横並びにする
ことで折り返し後のtop位置を合わせます。

以下が全体のソースになります。擬似要素のbeforeを利用していますので
残念ですがie6とie7には対応できません。

 body {
  background-color:#39f;
  text-align:center;
 }
 #main {
  background-color:#fff;
  margin:0 auto 0 auto;
  width:90%;
  overflow:hidden;
 }
 div div:before{
  display:block;
  height:5px;
  background-color:#f93;
  content:””;
  margin:-6px -200%;
  top:0;
 }
 div div {
  display:inline-block;
  width:300px;
  border:1px black solid;
  margin-top:5px;
  vertical-align:top;
 }

無題 1

   

fadalk 

    

fajldkfaj

   

faskldjfa

   

fkja;;lifd

   

kjfdaoijf

   

fjdisa;

まずポイントとなるのは親div(#main)の「overflow:hidden」です。
これがないと思いっきり横に伸びた線が表示されてしまい横スクロールバーも
表示されて不恰好です。これで余計なものは消します。

次のポイントは子div(コンテンツを想定)の「margin:-6px -200%」です。
マイナスマージンですね。ここら辺は私もまだ勉強不足でなんとなくしかわかってません。
余白をマイナスにとって幅や高さを増やす感じです。
またbefore/afterセレクタは「contents」を指定しないと出てきません。
線が途中で切れてしまう場合はマイナスマージンを多くとってください。

cssの小技が多すぎて覚えるのが大変です。

CSSで折り返しても線を引く方法 1

こんな需要がありました。
■ ←divタグ(コンテンツが入っている、高さ不定)
——- ←線(タグはなんでもいい)
として説明します。

基本レイアウトが
——-
■ ■ ■
——-
■ ■ ■
——-
■ ■ ■

となっています。この状態で画面を狭めると幅が足りなくなって折り返しますが、
折り返した時にも横の区切りが見やすいように線を引きたいというものです。

つまり折り返した時に2列になった場合
—–
■ ■
—–
■ ■
—–
■ ■
—–
■ ■
—–

としたいということです。
線の数が増減しますので、divやspanでbackground指定して書くのは難しいと思います。
線を最大数配置して「@media screen」でサイズ判定し、「display:none」と「display:block」を
切り替えても可能ですが、ものぐさな私は代案を考えました。

その方法は続きの投稿で…引っ張っておきながら大したことないです(笑)

divタグを横に並べる

divタグを横に並べる際、よく「foat:left」を使っているサンプルを見かけます。
横幅を固定してページを作る場合はさほど気になりませんでしたが、

横幅を縮めてコンテンツを折り返した場合「float:left」は高さを考慮して詰まります。
参考URL:http://www.understandard.net/css/css008.html
なので折り返してもレイアウトを保てるようにするには
「display:inline-block」を指定するといいです。これでブラウザの幅を狭められても
ある程度見やすさを保てます。

asdfaa

body{
background-color:aqua;
text-align:center;
}
#body {
background-color:#fff;
width:90%;
   max-width:1040px;
margin:5px auto 5px auto;
}
#body div{
width:300px;
border:1px black solid;
display:inline-block;
margin:5px 0 5px 30px;
text-align:left;
vertical-align:top;
   margin-left:30px;
   /display:inline;
   /zoom:1;
}

fasddfa

fasddfa

fasddfa

fasddfa

fasddfa

fasddfa


多分タブレットやスマートフォン向けの対策にもなります。
div#bodyを中心に寄せるために左右のmarginを「auto」に設定しています。

正規表現を使ってHTML整形

正規表現とは「複数の文字列を一つの文字列形式で表現する」ことです。
形式に合致しているかどうか調べることを「パターンマッチ」と言ったりしています。

VBAから正規表現を利用するには
「Microsoft VBScript Regular Expressions 5.5」を「参照設定」してRegExpオブジェクトを使うか
実行時バインディングで以下のように記述します。

    Dim Regex As Object
 
    Set Regex = CreateObject(“VBScript.Regexp”)

正規表現の使い方は他のサイトの方に任せるとして、
これを使ってHTMLの整形にチャレンジしてみます。

正規表現で開始タグから終了タグを検索します。

    Regex.Pattern = “(.|\n)*?()”

上記の正規表現では入れ子の場合に正確な開始タグと終了タグを取得できません。

(例)文字列『

あいえお

』の場合

ヒットする結果は『

あい』です。

当然欲しい結果は『』です(内側から処理していかないと正確にインデントできない)。
なので終了タグから開始タグを類推してもう一度正規表現を利用します。

    Temp = HTML
    With Regex
        ‘閉じがあるタグを変換
        .Pattern = “(.|\n)*?()”
        Do
            ‘パターンマッチ文字列の結果1件取得(取得できない場合はタグをすべて変換し終わった)
            Set Match = .Execute(Temp)(0)
         
            ‘終了タグから開始タグの正規表現作成
            nRegex.Pattern = “()”
         
            ‘パターンマッチ文字列の結果取得
            Set nMatches = nRegex.Execute(Match.Value)
         
            ‘最後の結果を取得
            Set nMatch = nMatches(nMatches.Count – 1)
         
            ‘開始タグから終了タグの文字列取得
            Contents = Mid$(Match.Value, nMatch.FirstIndex + 1)
         
            ‘文字列を変換
            Temp = Replace(Temp, Contents, “{” & CStr(idx) & “}”, , 1)
         
            ‘タグ削除
            Contents = Replace(Mid$(Contents, Len(nMatch.SubMatches(0)) + 1), Match.SubMatches(2), “”, , 1)
                     
            replacelist.Add vbCrLf & nMatch.SubMatches(0) & vbCrLf & _
                                vbTab & Contents & vbCrLf & _
                            Match.SubMatches(2) & vbCrLf, CStr(idx)
            idx = idx + 1
        Loop
Complete:
    End With

一気にコードを載せましたが、Match.SubMatches(3)で終了タグが取得できます。
間に同じタグが複数ある場合もあるので最後の結果を取得するために

    Set nMatch = nMatches(nMatches.Count – 1)

このようにしています。

その後完全な開始タグから終了タグまでの文字列を取得し
開始タグ、中の文字列、終了タグに分割します。

    Contents = Mid$(Match.Value, nMatch.FirstIndex + 1)

    Contents = Replace(Mid$(Contents, Len(nMatch.SubMatches(0)) + 1), Match.SubMatches(2), “”, , 1)

開始タグと終了タグを削除するには「PlainText」メソッドが適任かと思ったのですが、
「PlainText」メソッドはScriptタグとStyleタグに対して使うと中の文字列も消して返してきます。
他にもあるかもしれません。

PlainText(“aaa“)→aaa○
PlainText(“aaaaa”)→””×

なのでMid関数とReplace関数を併用して中の文字列を取得しています。
開始タグは

    nMatch.SubMatches(0)

これで取得できます。

このようにして内側からタグを順番に発見し、”{” & 連番 & “}”という形で変換していき、
元の文字列とセットで連番をKeyにしてCollectionに追加していきます。
すべてのタグが変換し終わったら、次のステップに進みます。

次は”{” & 連番 & “}”でCollectionにアクセスし元の文字列を取得して復元していきますが
もちろんただ戻すだけではありません。ここでインデントしながら元に戻していきます。

On Error Resume Next
    ‘文字列を復元しインデントする
    With Regex
        .Global = True
        .IgnoreCase = True
        .MultiLine = True
        .Pattern = “\{(\d*?)\}”
     
        Dim cnt As Long
        Dim idtcnt As Collection
        Set idtcnt = New Collection
     
        For idx = idx – 1 To 0 Step -1
            ‘変換リストから文字列取得
            Contents = replacelist(CStr(idx))
         
            ‘インデント対象の検索
            Set Matches = Regex.Execute(Contents)
         
            ‘インデント数の取得
            cnt = 0
            cnt = idtcnt(CStr(idx))
            For Each Match In Matches
                idtcnt.Add cnt + 1, CStr(Match.SubMatches(0))
            Next
            Temp = Replace(Temp, “{” & CStr(idx) & “}”, Replace(Contents, vbCrLf, vbCrLf & String$(cnt, 9)))
         
            If (cnt > 0) Then
                Temp = Replace(Temp, vbCrLf & String$(cnt, 9) & vbCrLf, vbCrLf)
            End If
        Next
    End With

例えば以下のようなHTML文字列があるとします。

テスト

これはテストです。

以下の順番で”{” & 連番 & “}”に変換されます。
0 テスト

1 {0}
2 これはテストです。
3 {1}{2}

これを逆順で文字列を復元するまえに文字列内にある”{” & 連番 & “}”に対してインデント数を
計算していきます。最初のインデント数は0です。

{3}インデント数=0
{1}{2}→{1}{2}のインデント数=0+1

{2}インデント数=1
これはテストです。

{1}インデント数=1
{0}→{0}のインデント数=1+1

{0}インデント数=2
テスト

復元の際に「取得したインデント数×vbTab」を改行に追加します。

    Temp = Replace(Temp, “{” & CStr(idx) & “}”, Replace(Contents, vbCrLf, vbCrLf & String$(cnt, 9)))

全コードを載せます。上記だけでは閉じがないタグ(imgタグ等)があるといびつになります。
またコメントやaspのスクリプトも有りますのでそれを先に変換する処理を加えています。

Private Function Surgery(HTML As String) As String
    Dim p As Variant
    Dim Temp As String
    Dim idx As Long
 
    Dim Regex As Object
    Dim Matches As Object
    Dim Match As Object
     
    Dim Contents As String
    Dim Letter As String
    Dim nMatches As Object
    Dim nMatch As Object
    Dim LastIndex As Long
    Dim NestContents As Long
 
    Set Regex = CreateObject(“VBScript.Regexp”)
 
    Dim tag0 As Collection
    Set tag0 = New Collection
 
    ‘閉じがないタグ
    With tag0
        .Add “



        .Add “

        .Add “
        .Add “


        .Add “


        .Add “”
        .Add “”
        .Add “”
        .Add “”
        .Add “”
        .Add “”
        .Add “”
        .Add “”
        ‘xml用
        .Add “”
    End With
         
    Dim nRegex As Object
    Set nRegex = CreateObject(“VBScript.Regexp”)
    With nRegex
        .Global = True
        .IgnoreCase = True
        .MultiLine = True
    End With
 
    ‘変換リスト
    Dim replacelist As Collection
    Set replacelist = New Collection
 
    With Regex
        .Global = True
        .IgnoreCase = True
        .MultiLine = True
     
        Temp = HTML
     
        ‘aspのスクリプトとコメントを変換(ユーザーによる改行があるため)
        .Pattern = “”
        Set Matches = .Execute(Temp)
        For Each Match In Matches
            Temp = Replace(Temp, Match.Value, “{” & CStr(idx) & “}”, , 1)
            replacelist.Add Match.Value & vbCrLf, CStr(idx)
            idx = idx + 1
        Next
     
        .Pattern = “”
        Set Matches = .Execute(Temp)
        For Each Match In Matches
            Temp = Replace(Temp, Match.Value, “{” & CStr(idx) & “}”, , 1)
            replacelist.Add Match.Value & vbCrLf, CStr(idx)
            idx = idx + 1
        Next
     
        ‘タグ内の改行を変換
        .Pattern = “”
        nRegex.Pattern = “\s\s+”
        Set Matches = .Execute(Temp)
        For Each Match In Matches
            Contents = nRegex.Replace(Match.Value, ” “)
            Temp = Replace(Temp, Match.Value, Contents, , 1)
        Next
     
        ‘連続した改行、スペースを削除
        .Pattern = “\s\s+”
        Temp = .Replace(Temp, “”)
     
        ‘閉じがないタグを変換
        For Each p In tag0
            .Pattern = p
            nRegex.Pattern = “<"
            Set Matches = .Execute(Temp)
            For Each Match In Matches
             
                ‘パターンマッチ文字列の結果取得
                Set nMatches = nRegex.Execute(Match.Value)
             
                ‘最後の結果を取得
                Set nMatch = nMatches(nMatches.Count – 1)
             
                ‘開始タグから終了タグの文字列取得
                Contents = Mid$(Match.Value, nMatch.FirstIndex + 1)
             
                ‘タグが全く同一の場合一気に変換するとインデントできなくなるので(特にbrタグ)変換は一つのみ
                Temp = Replace(Temp, Contents, “{” & CStr(idx) & “}”, , 1)

                replacelist.Add Contents & vbCrLf, CStr(idx)
                idx = idx + 1
            Next
        Next
     
On Error GoTo Complete
        ‘閉じがあるタグを変換
        .Pattern = “(.|\n)*?()”
        Do
            ‘パターンマッチ文字列の結果1件取得(取得できない場合はタグをすべて変換し終わった)
            Set Match = .Execute(Temp)(0)
         
            ‘終了タグから開始タグの正規表現作成
            nRegex.Pattern = “()”
         
            ‘パターンマッチ文字列の結果取得
            Set nMatches = nRegex.Execute(Match.Value)
         
            ‘最後の結果を取得
            Set nMatch = nMatches(nMatches.Count – 1)
         
            ‘開始タグから終了タグの文字列取得
            Contents = Mid$(Match.Value, nMatch.FirstIndex + 1)
         
            ‘文字列を変換
            Temp = Replace(Temp, Contents, “{” & CStr(idx) & “}”, , 1)
         
            ‘タグ削除
            Contents = Replace(Mid$(Contents, Len(nMatch.SubMatches(0)) + 1), Match.SubMatches(2), “”)
                     
            replacelist.Add vbCrLf & nMatch.SubMatches(0) & vbCrLf & _
                                vbTab & Contents & vbCrLf & _
                            Match.SubMatches(2) & vbCrLf, CStr(idx)
            idx = idx + 1
        Loop
Complete:
    End With
    Resume Restore
Restore:
On Error Resume Next
    ‘文字列を復元しインデントする
    With Regex
        .Global = True
        .IgnoreCase = True
        .MultiLine = True
        .Pattern = “\{(\d*?)\}”
     
        Dim cnt As Long
        Dim idtcnt As Collection
        Set idtcnt = New Collection
     
        For idx = idx – 1 To 0 Step -1
            ‘変換リストから文字列取得
            Contents = replacelist(CStr(idx))
         
            ‘インデント対象の検索
            Set Matches = Regex.Execute(Contents)
         
            ‘インデント数の取得
            cnt = 0
            cnt = idtcnt(CStr(idx))
            For Each Match In Matches
                idtcnt.Add cnt + 1, CStr(Match.SubMatches(0))
            Next

            ‘インデントを追加して文字列復元
            Temp = Replace(Temp, “{” & CStr(idx) & “}”, Replace(Contents, vbCrLf, vbCrLf & String$(cnt, 9)))
         
            If (cnt > 0) Then
                ‘余計な改行削除
                Temp = Replace(Temp, vbCrLf & String$(cnt, 9) & vbCrLf, vbCrLf)
            End If
        Next
    End With
 
     Surgery = Temp
End Function

たまに改行が残ったりしているのはご愛嬌です。またxmlにも一応対応しているつもりです。
閉じがないタグが他にもある場合は手動で追加してください。

またタグ内での改行は消しています。