C言語でCMSを書く その6 HTMLとCSSの生成

記事
IT・テクノロジー
さて、前回で最後にしようとおもったけど、まだ続けます。CSSがらみで、いろいろ書き足りないことがあったからです。これは前回のブログです。
っていうか、CSSについてはほとんど触れてなかったし。ということで、HOTPortでの、CSS生成と、HTMLとのからんだところなどをここではしっかりと書いていきます。

HTMLとCSSを組み合わせたいろいろなテクニックについては、ググったりすると、結構出て来ることが多いです。で、そういうテクニックを見ていると、ときに、「ここまでやらんでもできるでぇ」みたいなのも出くわします。
iOSのブラウザで背景画像が固定できない、っていう点についても、かなり面倒な解決法が書かれていることもありましたし、あと、メニューを左右のサイドに固定する方法とかも、むちゃくちゃ面倒な方法が書いてあったりしました。で、そういうのを参考にしつつ、一番単純にできそうなものを、利用しています。JavaScriptは使っていません。タブの切り替えも、通常の方法ではなく、ページ遷移を使っています。だから若干反応が遅いこともあります。
ただ、確実なのと、セキュリティ的に万全です。そのあたりで、最後に書いたように、打倒!WordPressなのでした。

CSSはなんかややっこしい
なんか、CSSって面倒なんです。大昔、CSSがないころは、HTMLの中にスタイルに相当するレイアウトとかがいろいろ簡単に書き込めて、それで、それなりになんとかなっていたんですが、いまは、ほとんどのWEBページが、パソコンとスマホの両方に対応する必要があるんで、そうなると、HTMLの中にスタイルを書き込んでしまうと、パソコンとスマホの両対応のWEBページができません。だから、HTMLでは、パソコンとスマホ両方に対応できるレイアウトの枠組みだけを書いておいて、その枠組みをCSSでパソコン用、スマホ用に対応するようにする、ということです。CSSの読み込みはHTMLのheadの部分に書いておくわけで、その際、画面の横方向の解像度に応じて、パソコン用CSSかスマホ用CSSか、というのを切り換えるようにします。
こんな感じですね。
----ここから----
<head>
 .....
<link rel="stylesheet" href="スマホ用CSSのURL" media="screen and (max-width: 1000px)">
<link rel="stylesheet" href="パソコン用CSSのURL" media="screen and (min-width: 1001px)">
</head>
----ここまで----
ここでは、横の画面解像度が1000ピクセル以下のときは、スマホ用のCSSを読み込み、1001ピクセル以上のときは、パソコン用のCSSを読み込むようにしています。

HTMLの生成部分
さて、HOTPortの画面を見ると、横長のパソコン画面では、こんな感じです。
ScreenShotPC.png

しかし、同じ画面を、横長を1000ピクセル以下にすると、こんな感じになります。これは、実はスマホではなくて、ブラウザの幅を小くしてみただけです。だから、あんまり縦長ではないわけです。
ScreenShotMV.png

メニューの位置が左右から上下になっていたり、文字が大きくなっていたりします。

こうなると、まず、HTML側では、CSS次第でどちらの画面にもなるようなHTMLを生成しておく必要があります。それを指定するのは、HTML側では、ほとんど divのタグのクラスで指定し、CSSでクラスごとに表示方法を書き込むという形になりますね。

まず、二つの画面の画像を比べるとわかる通り、一番上の「戻る」とかのバーは、パソコンでもスマホでも共通です。次に、パソコンで左右のメニューの部分がスマホでは上下のタブ見たいに変わっています。そこで、このHTMLの全体構造は、こんな感じになります。
----ここから----
//コメントは、スラッシュ二つでいきます。HTMLでは許されませんが。
<html>
//ページ全体の記述です。
<head>
//ヘッド部分。CSSへのリンクなど(上記)がきます。
</head>
<body>
<div class="wrapper">
//画面固定された背景の設定などをここでします。
//iOSのブラウザでは、背景の固定ができないので、
//この設定が必要になります。背景動画もここで指定します。
</div>
<header>
// 「戻る」などのメニューバーをheaderで定義し、
//CSSで画面上に固定します。
</header>
<div class="article">
//この部分に画面に現れる要素を書きます。
<div class="SideHeader">
//左のメニュー(あるいは上のタブ)を定義します。
</div>
<div class="main">
//この部分に中央にくる、ページ本体を書きます。
</div>
<div class="SideFooter">
//右のメニュー(あるいは下のタブ)を定義します。
</div>
</div>
</body>
</html>
----ここまで----
これで、HTMLの型枠は出来上がりで、これらについて、CSSのほうで、パソコン用かスマホ用かで、異るレイアウトを指定するわけです。

CSSの内容
まず、パソコン用の横長画面のレイアウトでは、以下のようにCSSで定義します。
----ここから----
//div の class="article"の設定です。
div.article{
//display をflexに指定することで、SideHeader, main, SideFooterを、
//左から右に並べるようにします。
    display:                flex;
//横幅は、右横のスライドバーのための1vw幅を差し引いて99vwに
//設定します。
    width:                  99vw;
}

//div class="SideHeader" の定義です。
div.SideHeader{
//フォントサイズの指定
    font-size:              1.2rem;
//左のメニューの上からの位置指定
    margin-top:             50px;
//下からの位置指定
    margin-bottom:          50px;
//画面左端からの位置指定
    margin-left:            1vw;
//画面右端からの位置指定
    margin-right:           84vw;
//メニューの幅指定
    width:                  14vw;
    padding:                0%;
    border-radius:          0.2em;
//背景の指定ですが、これはマクロ定義されています。
//このマクロ部分は、ブラウザから指定できるようにします。
    background:             var(--TopSideBackground);
//最後に、画面のスクロールに対して、スクロールしないことを
//fixによって明示します。これでメニューは左側に固定されます。
    position:               fixed;
}

//div class="main"の定義です。
div.main{
//ブロック指定します。
    display:                block;
//左のメニューの幅が14vwなので、そこから1vwだけ右に
//寄せたところにmain の左端が来るようになっています。
    margin-left:            15.0vw;
//これも同じで、右のメニューの部分から1vwだけ左に
//mainの右端が来るように設定します。
    margin-right:           15.0vw;
//最初に表示されるときは、左右メニューと同じ高さに
//設定します。
    padding-top:            50px;
//スクロールして、下に余裕をもたせます。
//これがないと、main に表示されているものが、
//ほかのメニューバーなどに隠れる可能性があります。
    padding-bottom:         50px;
    padding-left:           0.0%;
    padding-right:          0.0%;
//実際には、mainの中でさらに表示するものを設定するので、
//この部分の背景は無しにします。
    background:             none;
//幅は、69vwです。
//左右のメニューの幅が14で、間の隙間が1vwですから、
//左右あわせて、メニューの幅が30vwになり、画面幅が99vw
//なので、mainの幅は69vwになります。
    width:                  69vw;
// fix指定しないので、main の部分だけがスクロールします。
}

//div class="SideFooter"の定義です。
div.SideFooter{
    font-size:              1.2rem;
    margin-top:             50px;
    margin-bottom:          50px;
//左右のマージン設定は、SideHeaderの逆になっていて、
//左から84vw、右から1vwですね。
    margin-left:            84vw;
    margin-right:           1vw;
    width:                  14vw;
//あとは、SideHeaderと全く同じです。
    padding:                0;
    border-radius:          0.2em;
    background:             var(--TopSideBackground);
    position:               fixed;
}
----ここまで----
次に、スマホ用の設定です。今度は、SideHeader, main, SideFooterの要素が、縦にならび、SideHeader を画面の上のほうに固定し、SideFooterを画面下に固定し、そして、 main は固定せず、スクロールするように設定しています。
----ここから----
div.article{
    margin-top:             5%;
    margin-bottom:          0%;
    margin-left:            0%;
    margin-right:           0%;
    width:                  99vw;
//ここでは、display: flex;の指定をしません。
}

div.SideHeader {
//上にタブの形で表示するので、幅は99vwです。
    text-align:             center;
    font-size:              2.2rem;
    background:             var(--TopSideBackground);
    width:                  99vw;
//画面上の 「戻る」などのメニューバーの直ぐ下に
//表示されるようにします。
    top:                    72px;
//画面の上に固定します。
    position:               fixed;
}

div.main{
    display:                block;   
    background:             none;
    padding-top:            200px;
    padding-bottom:         200px;
    padding-left:           0px;
    padding-right:          0px;
    width:                  99vw;   
    hight:                  150vh;
//ここは、パソコン用と同じく、position: fixed;にはしません。
//スクロールできるようにしておきます。
}

div.SideFooter{
    text-align:             center;   
    font-size:              2.2rem;
    background:             var(--TopSideBackground);
    bottom:                 0px;
    width:                  99vw;
//画面の下に固定します。
    position:               fixed;
}
----ここまで----
ここまでのやり方を使えば、動きのある、ポップアップメニューなどにはなっていませんが、一応、結構操作しやすい画面になります。
まあ、実際、CSSとHTMLを駆使して、さらに JavaScriptを組み合わせて、ダイナミックに動きのあるWEBページなどがありますが、あまりに凝ったものだと、使う側が操作しにくくなることもあるし、また、ブラウザによっては上手く表示されない、なんてことがあるので、そういう要素を排除して、できるだけ簡単で、しかも操作しやすい、安全を狙ったWEBページのほうが良いと思います。
その代わり、CMSのほうで、HTMLの中にいろいろリンクしたり、検索エンジンを埋め込んだり、工夫することで、WEBページとして閲覧しやすくなると思います。

HTMLの生成部分ん工夫でもがく!
その関係で苦労したのが、実は、HOTPortのページの上にある「戻る」などのメニューバーです。

HOTPortでは、ログインすると、ユーザIDと、ログイン時のセッションIDを使ってアクセスすることにしています。セッションIDが外部に漏れると、アカウントを乗っ取ることができるので、それを避けるためにも、ブラウザの上に表示されるURLには、ユーザIDやセッションIDが書かれないようにする必要があります。そのため、ページからページに飛ぶ時には、<a href="URL"></a>でリンクを張るのではなく、全て <form>をつかってリンクするようになっています。そして、ユーザIDやセッションIDは、<input type="hidden" ...>でブラウザからWEBサーバに送るようにしています。これで、うっかり画面上のURLをコピーして、SNSに投稿したときなどに、セッションIDが埋め込まれたりしないようにしています。まあ、表示されている画面のHTMLのソースを解析して、そこのユーザIDやセッションIDを意図的に拡散させることもできますが、それは、普通はやりません。つまり、うっかりセッションIDをもらすようなことがないようにはなっています。

ということは、すべて、<form>をつかってページ移動をしているので、ブラウザの ←とか<などで表示されている戻るボタンを押すと、ブラウザによってですが、「フォームデータを送り直しますか?」などと聞いてきて、上手く戻れないことがあります。そうならないように、同じく<form>で戻れるようにする必要があったわけです。そこで、HOTPortでは、訪れたページをすべてスタックに積んで、それを<form>の中に埋め込んで、戻れるようにしているのです。
いや、この部分の実装はかなり面倒でしたが、一応、マトモに動いています。

自由にスタイル編集ができるようにする
さて、すでに、上でCSSのマクロ定義をつかっている部分をご紹介しましたが、ログインした状態で、自分が投稿したタイトル(記事)を見ると、こんな感じになっています。
ScreenShotInst0.png

さて、ここで、真ん中のあたりに、「編集する」「スタイル編集」という二つのボタンがあります。このうち、「スタイル編集」というので、投稿したタイトルの背景画面、ボタンの色、その他のスタイルが編集できます。
ここで、「スタイル編集」をクリックすると、以下の入力フォームがでてきます。
ScreenShotInstEdit.png

これで、
デスクトップCSSテンプレート(ファイル選択)
モバイルCSSテンプレート(ファイル選択)
の二つでファイルをそれぞれ指定することで、CSS全体を独自のものに置き換えることができます。そうすると、デフォルトのテンプレートとは全く違うスタイルに変更することも可能です。ただ、これはCSSがよくよく分かっている人だけができることですね。普通は、もっと簡単にスタイル編集できたほうが良いです。
で、次にある
背景画像(ファイル選択)
背景動画(ファイル選択)
によって、CSSは換えずに、背景画像と、背景動画を設定できるわけです。
そして、次に、背景色、ヘッダー背景、フッター背景、メニュー背景、段落背景、ボタン背景などが、設定できるようになっています。ここには、それぞれの項目の、CSSの中での設定で、background: という項目を指定するために使っています。簡単なのは、色指定です。#FFFFFFと書けば、そのまま背景は白くなります。
また、上では、ボタン背景として、rgba(0,127,127,0.7)と書かれていますが、この場合は、色がシアン(明い青緑)で、不透明度が0.7という意味です。ボタンの裏にある画像が0.3だけ透過して見える設定です。
ここに、画像の置いてあるURLを指定すると、背景が色ではなく、画像で表現されます。
これらを指定すると、CSSファイルの頭に、以下のような部分をくっつけます。
----ここから----
:root{
  --BackgroundImage:        url(背景画像のURL);
  --BackgroundColor:        white;
  --HeaderBackground:       linear-gradient(to right, rgba(255,255,255,0.0),rgba(255,255,255,0.7),rgba(255,255,255,0.0));
  --FooterBackground:       linear-gradient(to right, rgba(255,255,255,0.0),rgba(255,255,255,0.7),rgba(255,255,255,0.0));
  --TopSideBackground:      url(背景画像のURL);
  --ParBackground:          url(背景画像のURL);
  --ButtonBackground:       rgba(255,63,0,0.8);
  --MenuButtonBackground:   rgba(255,255,255,0.8);
  --HeadLineBackground:     linear-gradient(to right, rgba(255,255,255,0.0),rgba(255,255,255,0.9),rgba(255,255,255,0.9),rgba(255,255,255,0.0));
}
----ここまで----
これで、CSSの中で、
    background:             var(--TopSideBackground);
というような記述があったときに、この部分が、
  background:     url(背景画像のURL);
に置き換えられます。
まあ、背景色指定では、かなりいろいろなことができて、グラデーションの指定などもできるので、CSSをちょっとかじったら、いろいろ設定ができます。

そして、それらでできないことがあれば、CSSのテンプレート自体を書き換えることで、対応できます。それでもできないとなれば、HTMLの生成部分を書き換えることになりますが、それは、HOTPortのソースコードを変更しないといけませんね。

とはいえ、このあたり、スタイル編集やCSSの書き換えで、かなり自由度の高い設定ができる点で、普通のWordPressなどで管理されたWEBページよりは、ずっと自由に画面設定が変えられるし、背景画像や背景動画も自由に設定できる点で、ブログシステム、SNSプラットフォームとしては、かなりいろいろできるのではないかと思います。

というわけで、 HOTPortは、CMSの面では、打倒 WordPressです。

まとめに変えて
さて、今回は、HTMLとCSS、とくにCSSについて、いろいろ書いてみました。また、スタイル変更をブラウザから簡単にできる仕組みも、可能だよ、という話も書きました。これで、HOTPortのCMSについては、ほぼ畫き尽くしたかな、と思います。HOTPortのCMSに関する部分は、hotport.cというソースコードに書かれていますが、これだけで1万行です。これはデータベースやブロックチェーンに関する部分はほとんど含まれずに、これだけの量があります。かなり大変なプログラムで、バグの温床でもありました。ただ、現在はしっかり安定して動いています。次回のブログは、最終的なまとめになるか、書き忘れを追加するか、みたいなものになります。

ここに書いたCSSファイルは、以下のサービスにて御提供できます。また、HTML生成部分については、少々サイズが大きいですが、これも以下のサービスで御提供できます。

また、HOTPort全体については、以下のサービスで御提供いたします。



サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す