20200923のHTMLに関する記事は7件です。

(´ω`) CREATE TABLEパースできて楽になって余った時間でコーヒー

なし水を飲みながら書いてるわ。つーわけで書く。Qiitaの記事を書き始めてからこの時点でフォロワーは1人増えたぐらいで全く効果がなかった。まったく俺の書く記事が幼稚でそもそも読み手の意識していないちゃらんぽらんの野郎だって思われているかもしれない。実際その通りだ。かつては丁寧に書いていた時期もあったが今では一日の30分をQiitaに放り込んでいる。まるでゴミのようにだ。読者はその事に絶句しているかもしれない。嘲笑しているかもしれない。それが俺だ。丁寧に書けばいけるんじゃね?...と考えたがこれは質の問題のように思える。今日も最低限の記事を書いて眠ろう。ソースコードはわいの手元にある。完璧に動作する状態だがこの分だと陽の目を見ることもないだろう。終わりだ。そこで今まで通りだらだら書くスタイルにした。文字通りダラダラ書く。帰宅したおっさんが寝ながら書いているのか?それより酷い。みたいに書くぞ。

何作ったの

昔、私はある会社にいた。ウェブ系の案件を任された時に作ったユーティリティだ。これはCREATE TABLE文をパース出来る。JSON形式で。この案件ではエクセルに全てのテーブルとそのテーブルのスキーマが書かれていた。列に対する名前・型・入力値検証・制約・備考などだ。プロジェクトを作りこむ内に整合性が合わなくなってくる。ソースコード上はこちらに変更したが「そういやエクセル更新忘れた」と言っても担当は俺一人だったから何も問題はなかった。引継時は大問題だが。特にここらへんはもうCREATE TABLEのコメント文として真横に記載しておいた方がいいんじゃないか。ぐらいのレベルに思えた。でもそれじゃいけない。やっぱりエクセルに纏めておかないと。ってことで作った。とにかく列名をコピペするのが嫌だったし手入力だと遅いで一発でエクセルにコピーするために作った。

image.png

何組み合わせたの

単純だ。エディタはCODE-MIRRORを利用している。UIはいつも通りFOMANTIC-UIだ。テーブルのCSV化とテーブルを画像化したいこともあると思ってPNG化もできる。CHROMEの拡張機能だ。html2Canvasを使っても出来るが全て自作するのはよろしくない。本末点灯だ。エラーも出るようにしてある。

image.png

どうやってパースしてるの?

NEARLEYだ。NEARLEYというコンパイラを使えばJSの解析器を作れる。NEARLEYに.NEというファイル(BNFベースのNEARLEY構文)をぶち込めばパーサ(.JS)を出力してくれる。俺はNEファイルを書いてない。実際はGITHUBで楽に作れるライブラリはないかと探してたんだ。解析 mysql create table 语句,用于通过建表语句生成 model 代码文件。を持ってきた。

5ファイルあって

image.png

構文はこんな感じ

image.png

ソースコード

sample.html
<!doctype html>
 <html>
  <head>

   <title></title>

   <meta charset='utf-8'>
   <meta content='' name='author'>
   <meta content='' name='description'>
   <meta content='' name='application-name'>
   <meta content='notranslate' name='google'>
   <!-- GOOGLE:https://support.google.com/webmasters/answer/79812 -->
   <meta content='telephone=no,address=no,email=no,date=no,url=no' name='format-detection'>
   <meta content='noimageindex,notranslate,nosnippet,noarchive,nofollow,noindex' name='robots'>
   <meta content='width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no' name='viewport'>

   <link href='css/fomantic-ui/2.7.8.min.css' rel='stylesheet'>
   <link href='asset/manifest.json' rel='manifest'>
   <link href='asset/favicon.ico' rel='icon'>

   <style name='editor'>
     @import url('css/code-mirror/5.49.1.min.css');
     @import url('css/code-mirror/addon-5.49.1.min.css');
     @import url('css/code-mirror/mode-5.49.1.min.css');
     @import url('css/code-mirror/5.49.1.min.css');
  </style>
   <style name='font'>
     @font-face{
       font-family:'M+2VM+IPAG circle';
       src:url('asset/m+2vm+ipag-circle.ttf');
     }
  </style>
   <style>
     html,
     body{
       font:12px 'M+2VM+IPAG circle';
     }
     /*
      * 配置(中央)
      */
     body{
       display:flex;
       align-items:center;
       justify-content:center;
     }
     main{
       width:999px;
       height:100%;
     }
     .ui.grid{
       height:100%;
     }
     /*
      * 見栄(凹凸)
      */
     .ui.label,
     .ui.table,
     .ui.segment{
       border-bottom:2px solid rgba(34,36,38,.15) !important;
       box-shadow:rgba(16, 36, 94, 0.4) 0 2px 6px 0 !important;
     }
     /*
      * 調整(位置)
      */
     .ui.table,
     .ui.segment{
       margin-top:0;
     }
     /*
      * 調整(全体)
      */
     .ui.table>thead>tr>th,
     .ui.table>tbody>tr>td{
       padding:.2em;
     }
     /*
      * 調整(個々)
      */
     .ui.table>thead>tr>th:nth-child(2){
       width:5em;
     }
     .ui.table>thead>tr>th:nth-child(3),
     .ui.table>tbody>tr>td:nth-child(3),
     .ui.table>thead>tr>th:nth-child(4),
     .ui.table>tbody>tr>td:nth-child(4),
     .ui.table>thead>tr>th:nth-child(5),
     .ui.table>tbody>tr>td:nth-child(5){
       text-align:center;
       width:3em;
     }
     .ui.table>thead>tr>th{
       text-align:center;
     }
     .ui.table>tbody>tr:hover{
       cursor:pointer;
     }
     /*
      * 構造(エディタ)
      */
     #editor{
       display:flex;
       flex-direction:column;
     }
     #eidotr #editor-view{
       flex:1;
     }
     #editor #editor-controller{

     }
     /*
      * 設定(スクロールとフォント)
      */
     #editor,
     #editor .ui.segment,
     #editor .ui.segment .vue-codemirror,
     #editor .ui.segment .vue-codemirror .CodeMirror{
       height:100%;
     }
     #editor .ui.segment .vue-codemirror .CodeMirror{
       font:12px 'M+2VM+IPAG circle';
     }
     #viewer{
       height:100%;
       overflow-y:scroll;
     }
     /*
      * FOMANTIC-UI(が既に指定してる)
      * CREATE TABLE->(sql2json):<TABLE>群は
      * スクロールバーがあるとみっともないので非表示
      * #viewer::webkit-scrollbarは効かないので上書き
      */
     body ::-webkit-scrollbar {
       display:none;
     }
     .ui.label>i.icon{
       margin-right:0;
     }
     /*
      * FOMANTIC-UI
      * 2.7.8は古いFONTAWESOMEを利用中
      * ので新しいフォントを入れ直して個々に定義する
      * path:css/fomantic-ui/themes/default/assets/fonts
      */
      i.icon.file-csv:before    {content:'\f6dd';}
      i.icon.file-image:before  {content:'\f1c5';}
      /*
       * MODEL
       * CREATE-TABLEをTABLE化したモノ
       * 画像化した際(クロームの拡張機能による要素指定キャプチャ)影を残す
       * https://chrome.google.com/webstore/search/element%20capture?_category=extensions
       */
      #viewer div.model{
        padding-bottom:.7em;
        padding-right:.7em;
        padding-left:.7em;
        padding-top:0;
      }
      /*
       * sql2json
       * エラー時の色合わせ
       */
      .ui.label.error-message,
      .CodeMirror .error-line{
        background:#fff0f0 !important;
        color:#ff7373 !important;
      }
  </style>
 </head>
  <body>
   <main>

     <div class='ui grid internally celled'>
       <div class='row'>
         <div class='eleven wide column' id='editor'>
            <div class='ui labels blue' id='editor-controller'>
              <div class='ui label pointing below'>
                全テーブル
             </div>
              <a class='ui label' target='_blank' href='https://chrome.google.com/webstore/detail/html-elements-screenshot/mckfdaahjhmnchjihljdiakamamondld?hl=ja'>
                <i class='icon file-image'>
               </i><div class='ui detail'>PNG</div>
             </a>
              <a class='ui label' target='_blank' href='https://chrome.google.com/webstore/detail/download-table-as-csv/jgeonblahchgiadgojdjilffklaihalj?hl=ja'>
                <i class='icon file-csv'>
               </i><div class='ui detail'>CSV</div>
             </a>
              <div class='ui label error-message' v-if='hasErrSql2json'>
                {{err.message}}
             </div>
          </div>
           <div class='ui segment fitted' id='editor-view'>
             <codemirror ref='myCm' v-model='content'>  
            </codemirror>
          </div>
        </div>
         <div class='five wide column' id='viewer'>
           <div ref='models' v-for='(obj,n) in json'>
             <model v-model='json[n]'>
            </model>
          </div>
        </div>  
      </div>
    </div>
  </main>
 </body>
</html>

 <template id='model' type='text/x-template'>
   <div v-ui>
     <div class='ui divider horizontal'>
       {{table.name}}
    </div>
     <table class='ui table attached top single line unstackable celled fixed green'>
       <thead>
         <th></th>
         <th></th>
         <th></th>
         <th></th>
         <th></th>
      </thead>
       <tbody>
         <template ref='models' v-for='(obj,i) in table.columns'>
           <!-- ここ修正 -->
           <tr v-if='hasName(obj)' :class="[{'positive':highlight[obj.name]}]" @dblclick='highlightRow(obj)'>
             <td><span>{{getName(obj)}}</span></td>
             <td><span>{{getDataType(obj)}}</span></td>
             <td><span>{{getDataTypeParam(obj)}}</span></td>
             <td>
               <span>
                 <template v-if='getNullType(obj)'>
                   <i class='icon check'>
                  </i>
                </template>
              </span>
            </td>
             <td>
               <span>
                 <template v-if='getAutoIncrementType(obj)'>
                   <i class='icon check'>
                  </i>
                </template>
              </span>
            </td>
          </tr>
        </template>
      </tbody>
    </table>
  </div>
</template>

 <!-- native:code-mirror -->
 <script src='js/native/code-mirror/5.49.1.min.js'></script>
 <script src='js/native/code-mirror/addon-5.49.1.min.js'></script>
 <script src='js/native/code-mirror/mode-5.49.1.min.js'></script>

 <!-- native:sql2json -->
 <script src='js/native/lodash-4.17.15.min.js'></script>
 <script src='js/native/nearley/2.19.0.min.js'></script>
 <script src='js/native/nearley/grammar.js'></script>

 <!-- vue -->
 <script src='js/vue/2.6.10.js'></script>
 <script src='js/vue/code-mirror-4.0.6.min.js'></script>
 <script>
   Vue.directive('ui',function(el,binding,vnode){
     el.classList.add(vnode.context.$options.name)
   })

   Vue.component('model',{
     template:'#model',
     model:{
       prop:'table',
       event:'input'
     },
     props:{
       table:{
         required:true,
         type:Object,
         default:{}
       }
     },
     data:function(){
       return{
         highlight:{
         }
       }
     },
     methods:{
       /*
        * 行色
        */
       highlightRow:function(obj){
         if(this.hasName(obj)){
           var name = obj.name
           var toggle = (name in this.highlight) ? !this.highlight[name] : true
           this.$set(this.highlight,name,toggle)
         }
       },
       /*
        * 取得
        */
       getName:function(column){
         return column.name
       },
       getNullType:function(column){
         if(this.hasNullType(column)){
           return column.allow_null
         }
       },
       getDataType:function(column){
         if(this.hasDataType(column)){
           return column.data_type.type
         }
       },
       getDataTypeParam:function(column){
         if(this.hasDataTypeParams(column)){
           return column.data_type.params[0]
         }
       },
       getAutoIncrementType:function(column){
         if(this.hasAutoIncrementType(column)){
           return column.auto_increment
         }
       },
       /*
        * 検証
        */
       hasAutoIncrementType:function(obj){
         return 'auto_increment' in obj
       },
       hasDataTypeParams:function(obj){
         return this.hasDataType(obj) ? 'params' in obj.data_type : false
       },
       hasDataType:function(obj){
         return 'data_type' in obj
       },
       hasNullType:function(obj){
         return 'allow_null' in obj
       },
       hasName:function(obj){
         return 'name' in obj
       }
     }
   })

   /*
    * view-source:https://codemirror.net/mode/sql/
    */
   Vue.use(VueCodeMirror,{
     options:{
       scrollbarStyle  : 'simple',
       theme           : 'default',
       mode            : 'text/x-mysql',
       firstLineNumber : 1,
       tabSize         : 2,
       indentUnit      : 2,
       matchTags       : {bothTags: true},
       htmlMode        : true,
       autoCloseTags   : true,
       foldGutter      : true,
       lineNumbers     : true,
       lineWrapping    : true,
       styleActiveLine     : true,
       styleActiveSelected : true,
       extraKeys: {
         'Ctrl-A': 'autocomplete',
         'Ctrl-Q': function(cm){
           cm.foldCode(cm.getCursor())
         },
         'F11': function(cm){
           cm.setOption("fullScreen", !cm.getOption("fullScreen"))
         }
       }
     }
   })

   new Vue({
     el:'main',
     data:{
       err:{
         message:'',
         line:0,
         col:0
       },
       json:[],
       content:`
CREATE TABLE action_protocol (
  id int(11) NOT NULL AUTO_INCREMENT,
  createdbyuserkey varchar(40) NOT NULL DEFAULT '',
  userkey varchar(40) NOT NULL DEFAULT '',
  dt_created datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  servicekey varchar(40) NOT NULL DEFAULT '',
  information text NOT NULL,
  objectkey varchar(40) NOT NULL DEFAULT '',
  action varchar(50) DEFAULT '',
  PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE crm_reports (
  id int(11) NOT NULL AUTO_INCREMENT,
  entrykey varchar(40) NOT NULL,
  userkey varchar(40) NOT NULL,
  reportname varchar(255) NOT NULL,
  description varchar(255) NOT NULL,
  tablekey varchar(40) NOT NULL,
  dt_created datetime NOT NULL,
  dt_start datetime NOT NULL,
  dt_end datetime NOT NULL,
  date_field varchar(100),
  displayfields text NOT NULL,
  specials text NOT NULL,
  interval varchar(255) NOT NULL,
  filter text NOT NULL,
  defaultreport int(11) NOT NULL DEFAULT '0',
  basedonaddressbook int(11) NOT NULL,
  allow_select_fields int(11) NOT NULL DEFAULT '1',
  PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE adminactions (
  id int(11) NOT NULL AUTO_INCREMENT,
  dt_created datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  userkey varchar(50) NOT NULL DEFAULT '',
  urlvariables text NOT NULL,
  formvariables longtext NOT NULL,
  resellerkey varchar(50) NOT NULL DEFAULT '',
  companykey varchar(50) NOT NULL DEFAULT '',
  href text NOT NULL,
  PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

       ` 
     },
     watch:{
       content:{
         /*
          * 監視(入力)
          */
         deep:true,
         handler:function(newSQL,oldSQL){
          /*
            * 保存
            */
           localStorage.setItem('cache',this.content)

          /*
           * 解析
           */
          var self=this
          var editor=self.$refs.myCm.codemirror

          /*
           * 保存間隔は850ms
           */
          var processing = _.throttle(function(){

            // 消去:前回のエラー
            editor.removeLineClass(self.err.line,'wrap','error-line')

            try{
              // 変換
              self.sql2json()
              // 変換:正常
              self.err.message = ''
            }catch(exception){
              // 取得:エラーの情報と内容
              var errInfo = exception.message.split('\n')[0]
              var errContent = exception.message.split('\n')[2]
              // 整形:エラーとして表示するメッセージ
              self.err.message = errInfo + ':' + errContent
              // 取得:エラーの発生した行と列(https://www.regextester.com/97589 "Syntax error at line 111 col 1:: test")
              self.err.line = parseInt(errInfo.match(/line\s[0-9]+/g)[0].replace('line ','')) - 1
              self.err.col = parseInt(errInfo.match(/col\s[0-9]+/g)[0].replace('col ',''))
              // 追加:今回のエラー(https://codemirror.net/doc/manual.html#removeLineClass)
              self.$refs.myCm.codemirror.addLineClass(self.err.line,'wrap','error-line')
            }
          },850)

          /*
           * 処理
           */
          processing()
          /*
           * 表示
           */
          console.dir(
            this.json
          )
         }
       }
     },
     computed:{
       hasErrSql2json:function(){
         return this.err.message.length > 0
       }
     },
     methods:{
       init:function(){
         if('cache' in localStorage){
           this.content = localStorage.getItem('cache')
         }
       },
       sql2json:function(){
         this.json = new nearley.Parser(grammar).feed(this.content).results[0]
       }
     },
     created:function(){
       this.init()
       this.sql2json()
     }
   })
</script>

備考

CODE-MIRRORはmode/, addon/ とか別個に読み込まずにモジュール事に全ての*.jsをuglifyjs-folder使って1ファイルに纏めてる。CSSもcssclean *.css使って1ファイル化している。

さて

SQL以外にも何かできたらええよな。というお話でしたとさ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

# DMM英会話の予約ページをカスタマイズしてみた

DMM英会話の予約ページをカスタマイズしてみた

やったこと

  • DMM英会話を毎日続けているが予約ページが少し使いづらい
  • Google Chrome拡張のTamperMonkeyでカスタマイズして自分にとっての使い勝手を向上する

※ TamperMonkeyとはGoogle Chromeの拡張機能でユーザの任意のスクリプト(通称Greasemonkey scripts)を任意のページにて追加することができる。

追加した機能

  • 毎日の決まった時間に予約日時を変更するdailyボタンを追加する
    • (後ほどブックマークでよかったと気づく)
  • 開始時刻を変えた時に終了時刻を連動させる

デモ

スクリーンショット 2020-09-23 22.02.56.png

書いたコード

 // ==UserScript==
// @name         dmm english daily reserve
// @version      0.1
// @description  daily reserve button and change end time as start time.
// @author      tomyam
// @match       https://eikaiwa.dmm.com/list/*
// @grant        none
// @require     http://ajax.googleapis.com/ajax/libs/jquery/1.13.0/jquery.min.js
// ==/UserScript==

 $('h1').append('<br><button id="daily">daily button</button>');

// daily button to set daily schedule.
 $('#daily').click(function () {
     $('#start_time').val('13:00');
     $('#end_time').val('13:00');
     $('#e_list_index_select_gender1').val(2);
});

// end time changes when start time is changed. 
 $('#start_time').change(function () {
     $('#end_time').val($('#start_time').val());
     $('#e_list_index_select_gender1').val(2);
});

今後

  • 時刻だけ指定して完全に自動で予約できるようにする
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【初心者でもわかる】tableのtr要素に効かないCSS

どうも7noteです。テーブルを作っていて、trにCSSが効かない時に確認すること

tableのtrにはいくつかうまく反映されないCSSがあります。

とくに幅やbordreなどボックスに関連するCSS効かないので注意!

tr要素にも効くCSS

効く・・・というよりも、継承されて効いているってものが多そうです。

【フォント系】

  • color
  • font-size
  • font-weight
  • font-family

【テキスト系】

  • text-align
  • line-height
  • letter-spacing

【背景系】

  • background

tr要素には効かないCSS

【ボックス系】

  • width
  • height
  • margin
  • padding
  • border

trに効かないCSSがあるのはなぜ?

そういう仕様・・・というしかないのですが、あくまで私のイメージで考察してみました。

tr自体は表組みの1行を示す時に使われるタグで、tr要素の実体はどこにもありません。

つまり、実体のないモノに横幅を指定しても効かないし、borderを引こうにもなにもないところに線は引けない。
中にtd要素などを持ってはいますが、あくまでtrの役割は1行の意味だけなのでtr自身に対して直接なにかしようとしても効かないということなのかなと思います。

ただこれでいうとbackgroundだけは効くので何かが違うのかも・・・

初心者の方がコーディングする際は無理にtrに余白をとるのではなく、thやtd、もしくはtable要素自体にCSSを書くようにしましょう。
そして、trはCSSが効かないもの。と覚えてしまったほうが楽かもしれません。覚えることが多いと思うので、tr要素にCSSを書かなくても済むような組み方ができるようになっておいたほうがのちのち楽かもしれません。好みはあるかもですが。

まとめ

幅や高さ、余白と線はtr要素には効かない!!
いっそtrに装飾を使わないで済むほうがかも楽??です。

おそまつ!

~ Qiitaで毎日投稿中!! ~
【初心者向け】HTML・CSSのちょいテク詰め合わせ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

clearfix::afterの重要性

floatさせた要素が、上手く反映されない時の対処法

として、clearfix::afterを用いることが、解決法の1つとしてあります。
でもこれをきちんと理解出来てる方って少ないと思うんですよね。職業訓練校に通ってた時も、単に覚えてねーと言われた記憶があり、モヤモヤしていました。これを特に知りたくないかたは、flexboxを使いこなすことを推奨したいのですが、floatでしか再現出来ないこともあるので、これらの知識はmustだと思ってください。

index.html
<div class="container">
ここに画像が入ってるとする。
</div>

<div class="text-container"> 
/*以下を、全てフロートさせようとする*/
<p>テキスト</p>
<div class="text>
<p><img src="img/main-img"></p>
</div>
</div>

<div class="non-float">こいつはfloatさせたくない</div>
style.css
/*ここからは、Css*/
*{
margin:0;
padding:0;
}

.text{
float:left;
background-color:blue;
}

.text-container img{
float:right;
background-color:blue;
}

上の状態のままにしても、
スクリーンショット 2020-09-23 17.28.41.png
画像がみにくくて、申し訳ないのですが、non-floatクラスが、text-containerクラスに覆いかぶさるようになってしまっています。あらあら、そこはfloatしなくても良いのに。という状況ですね。これが、勉強を開始したばかりの頃に、とても悩まされました涙
この不必要なfloatを解除するために、

clearfix::after

を用いる必要が大いにあります。
::afterが分からない方は、ネットで調べてください。擬似要素ってやつです。
ちなみに、clearfixはクラスになるので、float解除させたいdivクラスの直前の親要素に設定をしてあげてください。イメージしにくければ、clear:bothだけで、対処することも初めのうちは良いと思います。何度も言ってますが、Web言語の勉強で必要以上の暗記は、しないでください。応用が効かなくなるので。

index.html
/*親要素にclearfixを設定しましょう!*/
<div class="text-container clearfix">
</div>
style.css
.clearfix::after{
clear:both;
display:block;
content:"";
}

cssのコードですが、1から説明していきたいと考えています。

1:clearについて

clearは、フロートの回り込みを解除します。

1(1)clear:left

直前の要素が、左にfloatされていて、左に回り込みをしたくない時に使う。

1(2)clear:right

直前の要素が、右にfloatされていて、右に回り込みをしたくない時に使う。

1(3)clear:both(よく使う気がする)

直前の要素の影響を一切受けない。

2:display:blockについて

これは、インライン要素、ブロック要素というものです。
インライン要素の場合は文字が、
ああああああ
と横並びになります。

しかしブロック要素では、





と縦並びになります。

今回の場合、divタグの回り込みを解除したいので、
display:blockを用いています。

3:contentについて

擬似要素に入れたい文字や記号がある場合、ここに記述する必要があります。
今回は何も入れないので、空白のみ入力されています。

style.css
.clearfix::after{
/*●を表現する場合*/
content:"●";
display:inline;
}

4::afterについて

divタグの直後を表現しています。

スクリーンショット 2020-09-23 18.48.33.png
図にしてみると、分かりやすいですかね!?

他にも、overflow:hiddenを使うパターンもありますが、これは背景画像を設定した場合、はみ出た部分が、デフォルトで非表示になってしまうので、時と場合によって使い分けないといけません。
スクリーンショット 2020-09-23 18.55.33.png

いやー説明するの難しいですねー。ご意見あれば、コメントくださいね。本日は、ここまで。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

overflow: scrollが反映されなかった原因

【目次】

1.overflow:scrollとは
2.原因
3.反省
4.最後に

1.overflow:scrollとは

親要素の表示範囲から、はみ出した子要素が存在する時、はみ出した分に関してはスクロール表示にすることができるというCSSの1つです。overflowというプロパティに対して様々な値を指定することができ、指定した値の種類によって、はみ出した子要素に対してどのような表示形式を指定するか決めることができます。

2.原因

widthとheightを指定していなかった為。(表示範囲を決める記述がなかった為)
「overflow」「効かない」といった単語を並べて検索したがヒットせず、初心者向けのoverflow解説記事を読んでいて気付きました。親要素からはみ出した分についての表示形式を定めるプロパティなのに、親要素のサイズが決まっていなければ、はみ出したかどうかの判定も行われていないのでスクロール表示がされないということですね。

3.反省

1.エラー原因の検索する前に、公式リファレンスや初心者向けの解説記事を読んでみる。

エラーの原因を直接的に探る検索も大切ですが、そもそもプロパティの使い方を1から読み直すこともエラーを解決する上では大切だと思います。私のような初心者のエラーは基本的な使い方に問題のある場合があります。あまりに基本的すぎるエラーは、現象を直接検索してもエラーの事例としてヒットしないことがあると思いました。

2.サイズ指定を忘れがち

検証ツールでサイズ指定していない部分を選択しても、コンテンツの分だけサイズがあるように表示されます。しかし、それはコンテンツを空にすれば表示領域は0になってしまうということです。コンテンツを入力しているとサイズが指定されていると錯覚してしまうことがあるので注意する必要があると感じました。
メモをしていなかったので例を出せませんが、サイズ指定をするだけでCSSが反映されないというエラーを解消できた例を他にも経験した記憶があるので、詰まったらサイズ指定を考えてみるというのも1つの方法かと思いました。

4.最後に

まだまだ初心者で誤った記事を投稿してしまうかもしれないので、変なことを書いている場合は指摘してもらえればと思います。
今後も自分がプログラミングをしていて気付いたことや、エラーの体験談とその解決について投稿していこうと思いますので宜しくお願い致します。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

3カラム横並びカードレイアウトのコーディング

はじめに

スクリーンショット 2020-09-22 23.10.01.png

WEB制作をしていると、こんな感じのカードレイアウトを作成することがあるので、コピペできるようにメモしておきます。

なるべく使い回しができるようにしていきますが、もっと汎用性高くできるわ!って人はお声掛けください。

まずはカード本体を作る

HTML

<div class="card">
    <div class="card__wrapper">
      <div class="card__img-box">
        <img
          src="https://cdn.pixabay.com/photo/2020/08/27/10/24/water-5521696_960_720.jpg"
          alt=""
          class="card__img-item"
        />
      </div>
      <div class="card__content">
        <h3 class="card__ttl">ダミーテキスト</h3>
        <p class="card__txt">
          ダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストが入ります。
        </p>
        <p class="card__txt">
          ダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストが入ります。
        </p>
      </div>
    </div>
  </div>

CSS(SCSS)

.card {
  &__wrapper {
    background-color: #fff;
    box-shadow: 5px 5px 5px #999;
  }

  &__img-box {
    position: relative;
    width: 100%;
    padding-top: 55%;
    overflow: hidden;
  }

  &__img-item {
    width: 100%;
    position: absolute;
    top: 50%;
    transform: translate(0, -50%);
  }

  &__content {
    padding: 20px;

    > *:last-child {
      margin-bottom: 0;
    }

  }

  &__ttl {
    font-size: 20px;
    margin-bottom: 15px;
    font-weight: 700;
  }

  &__txt {
    font-size: 16px;
  }
}

まずはカード本体を作成します。
「> *:last-child」の部分で何をしているかというと、仮にダミーテキストがなくなってタイトルだけになった場合にmargin-bottomを消してくれるようにしています。

こういうレイアウトのときに画像を背景でよく置くのですが、今回はコンテンツとして表示するという意識をもってあえてimgタグで置いています。
この方が背景よりも若干SEO的に有利になります。

また、背景でおくとCMS導入の際にHTMLにCSSで「background-image」を指定することになるのが自分的にあまり好きじゃないです…

横並びにする

 <div class="cards cards--col3">
  ~繰り返す~
    <div class="card">
      <div class="card__wrapper">
        <div class="card__img-box">
          <img
            src="https://cdn.pixabay.com/photo/2020/08/27/10/24/water-5521696_960_720.jpg"
            alt=""
            class="card__img-item"
          />
        </div>
        <div class="card__content">
          <h3 class="card__ttl">ダミーテキスト</h3>
          <p class="card__txt">
            ダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストが入ります。
          </p>
          <p class="card__txt">
            ダミーテキストダミーテキストダミーテキストダミーテキストダミーテキストが入ります。
          </p>
        </div>
      </div>
  ~ここまで繰り返す~
    </div>
  </div>

.cardのスタイルはそのままで、プラスして

CSS(SCSS)

.cards {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  margin: 0 -15px -30px;
}

.cards > .card {
  padding: 0 15px;
  margin-bottom: 30px;
}

.cards--col3 > .card {
  width: 33.33333%;
}

こんな感じです。
.cardsの部分で、ネガティブマージンを指定しているのはカード間にできるガターを打ち消すためです。
.card自体にはwidthは決めずに、親要素直下のcardに指定することで4カラムになった時でも、2カラムでもその都度対応できるかと思います。

まとめ

こんな感じで、コーディングに時間をかけて行きたくないので、ちょっとずつ貯めていきたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTMLにおける相対パスの開発環境と本番環境での違いをなんとかする

相対パスとは

相対パスは、HTMLにおいてはそのファイルからみた相対的な位置を表現したパスであり、要は同じフォルダにあるファイルなどを参照するのに使われます。
しかし、常にこれが同じになるとは限らず、かつ開発時と本番時を揃えるのが面倒くさい時にはなんとかしないといけません。
HTMLでは相対パスはbaseタグで決められます。JavaScriptではdocument.baseURIで取得できます。
しかしdocument.baseURIは読み取り専用です。

相対パスを変更する。

baseタグを利用すれば相対パスを変更できます。なんでか知らないですがdocument.baseURIでは変更できないので、baseタグにid属性をつけてhref属性を変更することで相対パスを変更できます。
この際にスクリプトなどは再読み込みされるようなので、パスが変更されることによって別のスクリプトが動作することになったりする可能性があります。

document.querySelector("#base").href=location.href;
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む