20200710のHTMLに関する記事は11件です。

Chrome Extentions "Krafty" 公開

Chrome Extention "Krafty"を公開しました。

開いているWebページのmeta情報やaltの確認、HTMLのネストの検証、要素のアウトラインの確認などができます。
マークアップエンジニアの方や、ディレクターの方には便利につかっていただけると思います。

名前は、New Orderのアルバムからいただきました。

ストア公開の申請時に、この拡張機能の使用にはホスト権限が必要なので、審査にかなり時間がかかると脅かされましたが、2日ほどで公開されました。
Googleさんありがとうございます。

Chrome Webstore
GitHub

機能紹介

Kraftyの4つの機能をご紹介します。

Head Checker

meta情報などを、ソースを開かずに確認できる機能です。
お客さんや一部ディレクターやなどソースを見るのに抵抗がある方や、コーディング時の漏れチェックのための機能です。

head.jpg

Nest Checker

タグのネストで、NGの部分を赤く表示して教えてくれる機能です。
技術的には、CSSのセレクタで、「このタグの直下にこのタグはNG」というのをひたすら指定しています。
問題なければ表示上何も変わりません。
構造上タグの組み合わせが膨大になってしまうので、漏れや間違いなどがないか、しばらく使って気付いたものを潰していこうと思います。

使用上の注意

許可するタグをnotで指定しているため、仕様上未知のタグはNG判定されてしまいます。
例:Google検索で使われているg-section
(キーワードがアレなのが多い気がしますが、たまたまです)

g-section2.jpg

g-section.jpg

テスト

試しに、Qiitaの記事ページで使用してみると・・・・あれ・・・・。

nest1.jpg

早速誤検出か・・・・・。

nest_selecter.jpg

でもdiv直下のdiv許可してるしな・・・・・。

nest_tag.jpg

あれ?閉じタグにもクラス名が?
あーなるほど、タグ名とクラス名の間が全角になっているので、<div>ではなく、未知のタグ<div class="logly-lift-ad-content">と認識されてNG判定されているようです。
タグのタイポも発見できる場合があることがわかりました。

Outline Checker

ページ内の要素のアウトラインを表示する機能です。
マークアップエンジニアの方が、要素がどのようにレイアウトされているか確認したり、スマホのCSSを書いているときに、謎の横スクロールの犯人の要素がなかなか見つからないときなどに使えると思います。

outline.jpg

Alt Checker

ページ内のimg要素のaltを表示する機能です。
お客さんや一部ディレクターやなどソースを見るのに抵抗がある方や、コーディング時の漏れチェックのための機能です。

alt.jpg

左上に画像があったんですね。気付きませんでした。

まとめ

最近無職となったので、ご興味持たれた会社様ご連絡お待ちしております。

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

【初心者でもわかる】html・cssで作る、簡単な三角形の作り方3選。

どうも、7noteです。今回はhtml・cssで吹き出しの三角形を作る3つの方法を解説していきます。

WEBサイトを作成する時、こんなデザインがよく見られます。

hukidashi_sankaku.png

吹き出し風のデザインのこんな三角形はよくでてきます。毎回出るのでその度適切な作り方を使い分けて綺麗なコーディングを意識しましょう!

方法1: borderで再現

これが一番綺麗な方法かなと思います。

index.html
<div class="fukidashi">borderで再現</div>
style.css
.fukidashi {
    width: 400px; /*吹き出しの横幅を指定*/
    background: #FCC; /*背景色にピンクを指定*/
    padding: 50px 20px; /*文字の上下左右に余白*/
    position: relative; /*三角形の表示位置の基準として指定*/
}
.fukidashi::after {
    content: ""; /*疑似要素では必ず書く*/
    width: 0; /*横幅を0に。*/
    height: 0; /*縦幅を0に。*/
    border: 15px solid transparent; /*透明のボーダーを作成*/
    border-top: 15px solid #FCC; /*上にボーダーを指定*/
    position: absolute; /*表示位置を設定するために指定*/
    bottom: -30px; /*吹き出しの下から、afterのコンテンツの高さ分下に*/
    left: calc(50% - 15px); /*左から50%のところから左に15pxずれたところ*/
}

border.png
わかり安く三角の色を変えると、こんな風になっています。↓
border2.png

解説

これはborderの特性をうまく利用して作られた三角形です。
要素の横幅と縦幅がない物に、borderを当てるとこんな状態になります。

上と右と下にそれぞれborderを入れた場合
border3:png.png

↓拡大↓
border4.png

見ていただくと上のボーダーと右のボーダーの境目がわかるでしょうか。
ボーダーの特性として、ボーダーの境目は斜めに分けられる。という特性があります。
この特性を利用し、上の三角にだけ色をつけ表示することで、三角形を再現できるという仕組みになります。

方法2: 四角形を重ねて再現

index.html
<div class="fukidashi">四角形を重ねて再現</div>
style.css
.fukidashi {
    width: 400px; /*吹き出しの横幅を指定*/
    background: #CCF; /*背景色に青を指定*/
    padding: 50px 20px; /*文字の上下左右に余白*/
    position: relative; /*三角形の表示位置の基準として指定*/
}
.fukidashi::after {
    content: ""; /*疑似要素では必ず書く*/
    width: 30px; /*横幅を30px*/
    height: 30px; /*縦幅を30px*/
    background: #CCF; /*背景色に青を指定*/
    position: absolute; /*表示位置を設定するために指定*/
    bottom: -15px; /*半分の高さを指定*/
    left: calc(50% - 15px); /*左から50%のところから左に15pxずれたところ*/
    transform: rotate(45deg); /*四角形を45度回転させる*/
}

shikaku.png
わかり安く四角の色を変えると、こんな風になっています。↓
shikaku2.png

解説

疑似要素で作成した四角を45度回転させて、上に重ねています。
基本的に三角形の書き方と変わりません。微妙に数字の違うところもありますが、仕組みは疑似要素をつかった物になるので解説は省きますが、このままだと四角形の後ろにもし模様や文字が重なった時隠れてしまうので注意が必要です!
また三角の頂点が90度にしか出来ないので、自由度がborderよりも低いのが欠点です。

方法3: 画像を入れて再現

index.html
<div class="fukidashi">四角形を重ねて再現</div>
style.css
    .fukidashi4 {
        width: 400px; /*吹き出しの横幅を指定*/
        background: #CCF; /*背景色に青を指定*/
        padding: 50px 20px; /*文字の上下左右に余白*/
        position: relative; /*三角形の表示位置の基準として指定*/
    }
    .fukidashi4::after {
        content: ""; /*疑似要素では必ず書く*/
        width: 30px; /*横幅を30px*/
        height: 15px; /*縦幅を15px*/
        background: url(triangle.gif); /*背景画像で三角を指定*/
        position: absolute; /*表示位置を設定するために指定*/
        bottom: -15px; /*吹き出しの下から、afterのコンテンツの高さ分下に*/
        left: calc(50% - 15px); /*左から50%のところから左に15pxずれたところ*/
    }

image.png

解説

画像の場合も疑似要素に背景画像を入れてposition:absoluteをつかって好きな位置に配置する方法になります。画像を使用する場面としては、borderなどで再現出来ないような場合に使うことが多いです。例えば三角の形が丸みを帯びているような形だったり、など。

まとめ

簡単な三角なら基本borderでほとんど再現出来ます。
三角形作成ツールなどもあるので、初心者の方は活用して作業速度をあげるのもいいと思います!

border三角形ジェネレーター

おそまつ!

(コメント・質問・ソースの指摘等なんでもウェルカムです!初心者の方でも気軽に質問ください!)

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

canvasで画像比較したい

canvasで画像比較したい

最近ffmpegを使って音をいじいじする機会がありました。
いろんなパターンで音を編集してみたのですが、音の変化を耳で感じるのに限界を感じ、視覚的に見る方法ないかなぁと思っていました。
そしたらffmpegには音の波形を画像で出す機能があるようで。

https://nico-lab.net/create_samples_waves_image_with_ffmpeg/

波形の画像を生成したは良いが、微妙な違いを確認するためには結局目を凝らすしかないという結果に。。
Rubyにはrmagickがありますが、javascriptでなんかできないかなぁと思いcanvasを使ってやってみることにしました。

どうやったか

概要

wave_1.pngwave_1.pngを用意し、canvasに順番にレンダリング。
レンダリングした情報を変数に格納。
画像を比較して差分がある箇所だけ色を付ける。

index.html
<body>
  <p>image1</p>
  <img id="image_1" src="wave_1.png" />
  <p>image2</p>
  <img id="image_2" src="wave_2.png" />
  <p>diff</p>
  <canvas id="my-canvas" width="480" height="270"></canvas>
  <script type="application/javascript" src="canvas.js"></script>
</body>

class WaveDiffChecker {
  load() {
    this.image1 = document.getElementById("image_1");
    this.image2 = document.getElementById("image_2");
    this.c1 = document.getElementById("my-canvas");
    this.ctx1 = this.c1.getContext("2d");

    this.width = this.image1.clientWidth;
    this.height = this.image1.clientHeight;

    this.checkWave();
  }

  checkWave() {
    this.ctx1.drawImage(this.image1, 0, 0, this.width, this.height);
    const frame1 = this.ctx1.getImageData(0, 0, this.width, this.height);
    this.ctx1.drawImage(this.image2, 0, 0, this.width, this.height);
    const frame2 = this.ctx1.getImageData(0, 0, this.width, this.height);

    const pixels = frame1.data.length / 4; // 同じ画像サイズなのでdotsは1つでOK

    for (let i = 0; i < pixels; i++) {
      const index = i * 4;
      const isSame = [0, 1, 2].every(value => {
        return frame1.data[index + value] === frame2.data[index + value];
      });
      frame1.data[index] = isSame ? 0 : 100; // Red値
      frame1.data[index + 3] = isSame ? 0 : 100; // Alpha値
    }
    this.ctx1.putImageData(frame1, 0, 0);
  }
}

const diffChecker = new WaveDiffChecker();
diffChecker.load();


スクリーンショット 2020-07-10 22.09.23.png

ポイント

this.ctx1.getImageData(0, 0, this.width, this.height)
getImageDataの返り値はimageData
であり、imageData.dataでUint8ClampedArray
にアクセスできます。
このArrayはRGBAの順で0から255のデータを持っています。

//1ピクセルの構成
frame1.data[0] //=> 0(Red)
frame1.data[1] //=> 255(Green)
frame2.data[2] //=> 100(Blue)
frame3.data[3] //=> 150(Alpha)

各ピクセルの要素を順に確認していき、RGBAのどこかに差分がある場合のみ色をつけています。

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

初心者によるプログラミング学習ログ 366日目

100日チャレンジの366日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
366日目は、

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

【HTML】Google Mapの埋め込み

はじめに

Google MapからHTMLをコピーして貼り付けることでサイトにGoogle Mapを埋め込むことができる。

実装方法

1. Google Mapで目的地を検索 → 共有をクリック

スクリーンショット 2020-07-09 18.06.40.png

2.地図を埋め込むをクリック → HTMLをコピー
地図のプレビュー画面が表示される

スクリーンショット 2020-07-09 18.09.06.png

Mapのサイズを選ぶこともできる
スクリーンショット 2020-07-09 18.14.25.png

       表示サイズ
横 400px × 縦 300px
横 600px × 縦 450px
横 800px × 縦 600px
カスタムサイズ 自由にカスタマイズ(px単位)

↓ タグ内の width height でもサイズを調整することが可能

sample.html
<iframe src="https://www.google.com/maps/embed?
pb=!1m18!1m12!1m3!1d3240.827853398542!2d139.76493611522864!3d35
.68124053757879!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2
!1s0x60188bfbd89f700b%3A0x277c49ba34ed38!2z5p2x5Lqs6aeF!5e0!3m2
!1sja!2sjp!4v1594286431753!5m2!1sja!2sjp"
 width="600" height="450" frameborder="0"
 style="border:0;" allowfullscreen="" aria-hidden="false"
 tabindex="0"></iframe>

3.コピーしたHTML(iframeタグ)を埋め込みたいHTMLにペーストして完成
スクリーンショット 2020-07-09 18.23.58.png

赤いピンの位置を調整

↓ iframeタグを下記のように書き換える

sample.html
<iframe
src="https://www.google.com/maps?
output=embed&z=15&ll=35.6812405,139.7649308&q=東京駅"
width="600"
height="450"
frameborder="0"
style="border: 0;"
allowfullscreen=""
aria-hidden="false"
tabindex="0"
/>

これらの値を変えることで地図をカスタマイズすることができる

iframeタグ内の記述            調整部分             
&z=15     縮尺 0〜23で調整可
&q=住所・建物名 住所・建物名
&ll=緯度,経度     地図の中心点 Google Mapで検索した地点のURLに緯度・経度が記載されている

↓ 赤線:緯度 / 青線:経度
スクリーンショット 2020-07-10 12.05.29.png

ピンの位置を右下に移動することができた!
スクリーンショット 2020-07-10 12.27.03.png

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

手動でABテストするためのコンテンツの出し分けのサンプル(Javascript+Cookie)

はじめに

実現したい事はWebサイトで
特定の画像/文章/デザインなどの部品を2パターン用意し、
ランダムで表示してその結果を後で
GoogleAnalyticsなどで検証するというものです。
※コードの例ではGAのイベントトラッキングを活用します。
rabel.png
オプティマイズや別の専用ツールなどもあるのですが、
ツールの縛りがある、使い辛い、まずは気軽に試したい、
という時に不便なので作りました。(個人サイトの場合など含め)

(利用例)
画像A / 画像B どちらを表示したほうがCVRが良いか?
※GA等の解析ツールにデータを送信し、後で分析をかけます。

補足:
コードは汚いので仕組みそのものや部品とりとしてご活用ください。

仕様

概要:
特定のIDを持つ要素に対してA/Bパターン2種類の中身(HTML)を用意し、
それをおよそ1/2の確率でランダムで表示します。
結果はCookieに記録し、次回以降該当のCookieが存在する場合、
同じ結果を表示します。
※Cookieを消したらまた1/2の確率でどちらかが表示されます。

これらの結果を表示する度に、GAにイベントとして
データを送信するというサンプルです。
※GAじゃなくてもコードをJSやHTMLで連携する類のものなら何でも可

使う言語:javascript+html+css
補足:cookieを活用します

Javascriptコード

※デバッグ用と記載のある関数/コードは使用しなくとも大丈夫です。

<script>

window.onload = function() {

const thiscookiename = 'abtest';
//Cookieの名前

const btag = "<p style='background-color:#ffffee;width:200px;'>私がオススメするのは<br>クレープです。<br>";
//Bパターンのタグをここに記載

const yosoid1 = 'abtest';
//変更対象の要素のID

const yukokigen = 7;
//Cookieの有効期限(日)

const abeventname = 'testcase2020';
//GAイベント名称

const abeventcategory = 'ABTEST';
//GAイベントカテゴリー

//初期設定
//END


//0か1の乱数生成 Math.random()で0~1の間の乱数、2倍にしたものを整数にする
let abtestran = Math.floor( Math.random() * 2 );

const expire = new Date();
expire.setTime( expire.getTime() +yukokigen *24*60*60*1000 );
//Cookie用日時と有効期限の設定

//Cookieの有無を確認
if(GetCookieABtestOnly(thiscookiename) == null){
    document.cookie = thiscookiename + '=' + abtestran + '; expires=' + expire.toUTCString();
    //存在しなかったらCookie書込み

}
else{
    abtestran = GetCookieABtestOnly(thiscookiename);
    //存在する場合はテスト判定用数値を設定する
}


if(abtestran==1){

    //Bの時の処理

    document.getElementById(yosoid1).style.display = 'inline-block';
    //要素を表示するスタイルに変更

    document.getElementById(yosoid1).innerHTML = btag;
    //Bパターンのタグを代入

    document.getElementById('kekka').innerHTML = abtestran + "が値です";
    //デバッグ用


//GAイベント送信
gtag('event',abeventname, {
  'event_category' :abeventcategory,
  'event_label' : 'B_PT'
});
//endGA


}

//Aの時(イベント送信以外何もしない)
else{
    document.getElementById(yosoid1).style.display = 'inline-block';
    //要素を表示するスタイルに変更

    document.getElementById('kekka').innerHTML = abtestran + "が値です";
    //デバッグ用

//GAイベント送信
gtag('event',abeventname, {
  'event_category' :abeventcategory,
  'event_label' : 'A_PT'
});
//endGA

}


}
//onload終了



//Cookie取得用の関数
function GetCookieABtestOnly( name )
{

let result = null;
const cookieName = name + '=';
const allcookies = document.cookie;

const position = allcookies.indexOf( cookieName );

if( position != -1 )
    {
        startIndex = position + cookieName.length;

        endIndex = allcookies.indexOf( ';', startIndex );
        if( endIndex == -1 )
        {
            endIndex = allcookies.length;
        }

        result = decodeURIComponent(
            allcookies.substring( startIndex, endIndex ) );
    }

return result;
}



//デバッグ用Cookie削除
function deleteCookie(cockname) {
date = new Date();
date.setTime( date.getTime() - 1 );
document.cookie = cockname + '=; expires=' + date.toUTCString();

document.getElementById('kekka').innerHTML = "削除しました";

}


</script>

HTMLのコード

※デバッグ用と記載のある部分は使用せずとも大丈夫です。

▼変更対象の要素:<br>
<!-- Aパターンの記載 -->
<div id="abtest" style="display:none;">
<p style="width:200px;background-color:#ffeeee;">
私がオススメするのは<br>
【タピオカ】です。<br>
</p>
</div>

<br><br>

Cookieの値を表示:デバッグ用<br>
<div id="kekka">
</div>

<br>

<div>
Cookieの削除:デバッグ用<br>
<input type="button" value="Cookie削除" onclick="deleteCookie('abtest');" style="cursor:pointer;">
</div>

解説(重要そうな部分)

ランダム表示用の変数を作る:
let abtestran = Math.floor( Math.random() * 2 );
ランダム表示用に0か1の乱数を生成します。
Math.random()で0~1の間の乱数を、2倍にしたものを整数にする事で、
0か1だけになります。

判定用(cookie有無):

別関数としてcookieの有無を確認するものを用意し、
nullだった場合はcookieを書き込みします。
存在していた場合は、Cookieの値をAB判定用の変数に代入します。

if(GetCookieABtestOnly(thiscookiename) == null){
document.cookie = thiscookiename + '=' + abtestran + '; expires=' + expire.toUTCString();
}
else{
abtestran = GetCookieABtestOnly(thiscookiename);
}

判定用:ABのどちらか
if(abtestran==1){}else{}
単純に1か0でAとBを判定します

コンテンツを表示する部分

HTML側:
<div id="abtest" style="display:none;">
Bを表示する時に一瞬、Aの画像が表示されるのを防ぐため、
HTML側はスタイルdisplay:noneで要素を隠しておきます。

JS側:
document.getElementById(yosoid1).style.display = 'inline-block';
Javascript側でスタイルを変えて、表示します。

document.getElementById(yosoid1).innerHTML = btag;
特定のIDを持つ要素に、JS内で記述しておいたBパターンの
タグを挿入します。

後述

お読みいただきありがとうございます!

ポイントは1/2ランダムで出し分けと、Cookieで記録しておくという
部分だと思います。※毎回完全ランダムだとユーザーが困るので…

また、今回AパターンはHTMLに記述しておいて、BパターンはJS内に記載しましたが、
両方display:noneにしておいて、display:blockにするやり方もありますね。

応用すればもっと便利に出来るはずですので、
参考という形にしていただければと思います。

動作サンプルも置いておきます。
http://allcountry.sakura.ne.jp/biz/code/javascript/20200709/cookieabtest.html

pta.png

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

【flex-box】 html css フレキシブル対応 レイアウト 基本

【ゴール】

flex-box忘れていたので、振り返り

【コード】

何はともあれ、「display: flex;」を親要素に指定

flex-wrap: wrap;

*折り返し
*HTMLにboxとcontentクラスを用意

スクリーンショット 2020-07-10 18.15.39.png

css.hoge.css
.box{
  background-color: lightgreen;
  min-height: 200px;
  widows: 100%;
  display: flex;
  flex-wrap: wrap;
}

.content{
  margin: 10px;
  height: 100px;
  width: 30%;
  background-color: green;


justify-content: space-between;

スクリーンショット 2020-07-10 18.22.23.png

hoge.css
.box{
  background-color: lightgreen;
  height: 200px;
  widows: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.content{
  background-color: green;
  height: 100px;
  width: 100px;
}

justify-content: center;

*横軸の位置

スクリーンショット 2020-07-10 18.09.14.png

css.hoge.css
.box{
  background-color: lightgreen;
  height: 200px;
  widows: 100%;
  display: flex;
  justify-content: center;
}

align-items: center;

*縦軸の位置

スクリーンショット 2020-07-10 18.09.28.png

css.hoge.css
.box{
  background-color: lightgreen;
  height: 200px;
  widows: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

抜けていたので、復習含めて書きました。
bootstrapを使えばあまり使わずすみますが、覚えていて損はないかと

【合わせて読みたい】

■ 【Rails new】Ruby on rails アプリケーション作成
https://qiita.com/tanaka-yu3/items/3fe1ed2852c6513d3583

■ 【devise】 rails g devise:install ができない、、時こそ!!
https://qiita.com/tanaka-yu3/items/8a2002921cda080907f8

■ 【メソッド集】 rails メソッド まとめ 基礎 随時追加
https://qiita.com/tanaka-yu3/items/89abad875187494bec53

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

色々なCSSアニメーションつくってみた 10日目【WEBサイトを作る30日チャレンジ】

CSSだけでアニメーションを作る(trasition及び@keyframeを使用)

 ・hoverした際に動くアニメーションとしました
 ・アニメーション以外は前回作ったシャーロックホームズのテンプレを一部利用しています
 ・画像はフリーのものを使用しました

お世話になったサイト様

@7968様 @keyframeとanimation
@7968様 trasition関連

完成物

ezgif.com-video-to-gif (10).gif

コード

<!DOCTYPE html>
<html>
<head>
<title>CSS 3D Ratating Image Gallery</title>
<link rel="stylesheet" type="text/css" href="30_10.css">
</head>
<body>
  <nav id="nav-drawer">
    <input type="checkbox" id="check" id="nav-input">
    <label for="check" class="checkbtn open"></label>
    <label for="check" class="checkbtn close"></label>
    <label class="logo"><a href="#" class="logo">Sherlock</a></label>
    <ul>
      <li><a class="active" href="#">ホーム</a></li>
      <li><a href="#">会社概要</a></li>
      <li><a href="#">事業内容</a></li>
      <li><a href="#">お問い合わせ</a></li>
      <li><a href="#">採用情報</a></li>
    </ul>
  </nav>

  <div class="description">マウスをあわせると変化する</div>
<div class="animate1"><a href="#">アニメーション1</a></div>
<div class="animate2"><a href="#">アニメーション2</a></div>
<div class="animate3"><a href="#">アニメーション3(2秒後変化)</a></div>
<div class="animate4"><a href="#">アニメーション4</a></div>
    <div class="container">
        <div class="box">boxを中心にくるくるアニメーション
            <span style="--i:1;"><img src="トムとジェリー.png"width="300px" height="300px"></span>
            <span style="--i:2;"><img src="トムとジェリー.png"width="300px" height="300px"></span>
            <span style="--i:3;"><img src="トムとジェリー.png"width="300px" height="300px"></span>
            <span style="--i:4;"><img src="トムとジェリー.png"width="300px" height="300px"></span>
            <span style="--i:5;"><img src="トムとジェリー.png"width="300px" height="300px"></span>
            <span style="--i:6;"><img src="トムとジェリー.png"width="300px" height="300px"></span>
            <span style="--i:7;"><img src="トムとジェリー.png"width="300px" height="300px"></span>
            <span style="--i:8;"><img src="トムとジェリー.png"width="300px" height="300px"></span>
        </div>
    </div>
</body>
</html>

*
{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
.description{
  top:0;
  color: black;
}
a{
  text-decoration: none;
  color: black;
}
.container
{
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
}
/* 一個目 */
.animate1{
  background-color: rgb(192, 240, 255);
  width: 150px;
  top: 0;
  margin: 10px;
  text-decoration: none;
}
.animate1:hover{
  animation-name: none;
  background-color:blue;
  color: black;
  width: 300px;
  transition-duration: 5s;
}
/* 二個目 widthが5秒で変化、bgcがすぐに変化*/
.animate2{
  background-color: rgb(192, 240, 255);
  width: 150px;
  top: 0;
  margin: 10px;
  text-decoration: none;
  transition-property:width;
}
.animate2:hover{
  animation-name: none;
  background-color:blue;
  color: black;
  width: 300px;
  transition-duration: 5s;
}
/* 3個目 2秒まってスタート*/
.animate3{
  background-color: rgb(192, 240, 255);
  width: 150px;
  top: 0;
  margin: 10px;
  text-decoration: none;
}
.animate3:hover{
  animation-name: none;
  background-color:blue;
  color: black;
  width: 300px;
  transition-delay:2s;
  transition-duration: 3s;
}
.animate4{
  background-color: rgb(192, 240, 255);
  width: 150px;
  top: 0;
  margin: 10px;
  text-decoration: none;
}
.animate4:hover {
  animation-name: fadeIn;
  animation-duration:5s;
}
@keyframes fadeIn {
  0% {
      opacity:0;
  }
  100% {
      opacity:1;
  }
}
.box{
  position: relative;
  width: 200px;
  height: 200px;
  transform-style: preserve-3d;

}
.box:hover
{
    position: relative;
    width: 200px;
    height: 200px;
    transform-style: preserve-3d;
  animation: animate 22s linear infinite;
}
.box span
{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    transform-origin: center;
    transform-style: preserve-3d;
    transform: rotateY(calc(var(--i) * 45deg)) translateZ(400px);
    -webkit-box-reflect: below 0px linear-gradient(transparent,transparent,#0004);
}
.box span img
{
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
@keyframes animate
{
    0%
    {
        transform: perspective(1000px) rotateY(0deg);
    }
    100%
    {
        transform: perspective(1000px) rotateY(360deg);
    }
}
/* ↓ナビゲーションバー */
nav{
  background-color: black;
  width: 100%;
  top:0;
}
#check,
#nav-input{
  display: none;
}
.checkbtn{
  font-size: 30px;
  color: white;
  float: right;
  line-height: 80px;
  margin-right: 40px;
  cursor: pointer;
  display: none;
}
label.logo a{
  color: white;
  font-size: 40px;
  line-height: 80px;
  font-weight: 600;
  text-decoration: none;
  margin-left:30px;
}
nav ul{
  float: right;
  margin-right: 60px;
}
nav ul li{
  display: inline-block;
  line-height: 80px;
  margin: 0 2px;
}
nav ul li a{
  color: #f2f2f2;
  text-decoration: none;
  font-weight: 600;
  font-size: 20px;
  padding: 7px 15px;
  text-transform: uppercase;
  text-decoration: none;
}

学べたこと

 ・trasitionの動きと記述の流れ
 ・@keyframeとanimationの関係及び応用

感想

 いままであまり気にしていなかった、trasitionやkeyframeの理解が進み、レパートリーが増えました。
 今回作成したものは簡単なものですが画像等を用いると、企業向けの面白いサイトができそうです。
 くるくる実装は建築系や、面白い雑貨屋さん等のオシャレなサイトにありそうですね!
 今回は以上となります。
 
 ここは違う、ここはこうしたほうが良いかも?等々ございましたらご指摘いただけますと幸いです。
 最後までみていただき、ありがとうございました。
 

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

HTMLの基本(備忘録)

HTMLの概要

Hyper text markup languageの略。
Web上の文書を記述するためのマークアップ言語。

マークアップとは?
文章がどのような構造になっているかを明確化する作業のこと。
どこが見出して、何がリンクなのか、構造化すること。

HTMLの基本

HTMLの冒頭に、この文書はHTMLで書かれていることを宣言するDOCTYPE宣言が必要。
これ→ <!DOCTYPE html>

コメント <!-- ここに文書 -->

 言語を表す。 ja=日本語

< > HTMLタグ
開始タグから始まり、内容を挟んで、終了タグまでが1つのまとまり
このまとまりを要素と呼ぶ。タグ内に文字を要素名という。

head と body

HTML文書の中身を大きく分けるとhead要素とbody要素

head要素内には文書に関する「メタ情報」
body要素には「コンテンツ」

メタ情報には、ページタイトル、外部スタイルシートの場所、外部JavaScriptファイルの場所、文字エンコーディング情報、ページの概要
meta charset="UTF-8" も忘れずに記述〜。

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

Javascriptで日付の連動更新をする

命題

JavaScriptを使って、二つ(以上)ある<input type="date">の一方が更新されたとき、もう片方を同じ値にしたい。
ブラウザはChrome 83を使用。

想定される使用例

検索期間を2組の<input type="date">で表し、例えば検索終了日を変更した際に、検索開始日より過去の日付だったら開始日を終了日と同じにする。

HTMLサンプル
<div>
  検索期間: <input id="DateSince" name="DateSince" type="date" value="2020-07-10"><input id="DateUntil" name="DateUntil" type="date" value="2020-07-10">←こちらを変更すると左側の日付も変わります。
</div>

具体的には上記のコードで、DateUntilを2020-7-09に変更した場合、DateSinceも2020-7-09に書き換わるようにする。

実際の実装では逆の処理(DateSinceをDateUntilより未来にした場合、DateUntilをDateSinceと同じ値にする)も必要だが、説明簡略化のために省く。

具体的な方法

イベント自体の作成は簡単。

DateUntil「変更」時に発生させるJSイベント
function dateUntilChanged(e) {
  const dateSince = document.getElementById("DateSince");
  const value = e.target.value;
  if (dateSince.value < value) {
    dateSince.value = value;
  }
}

問題はこのイベントをどのタイミングで発火させるかである。

ダメな例: changeイベントを使う

変更されたのなら素直にchangeイベントを使えばいいじゃん、とついつい考えてしまいがちだが、それは残念ながら間違い。

changeイベントを使用したJS
document.getElementById("DateUntil").addEventListener("change", dateUntilChanged);

こうすると(少なくともChromeでは)DateUntilが打鍵されるたびにイベントが発火するので、「2020」とキーボード入力する際に2→0→2→0と入力するためにDateSinceが0002年になってしまう(当然、日付の変更条件は満たされなくなるので、0002年のまま変更されない)。

この動作は正直言って好ましくない。イベントをいちいち発火するコストも問題だ。

よりよい例: blur(フォーカスアウト)イベントを使う

入力されるたびにイベントを発生させるのではなく、Dateの入力が完了した後、Tabキーや<input type="date">の外部をクリックすると起こるようなイベントがあればいい。
そこで登場するのがblurイベントだ。

blurといきなり言われても分かりづらいので(個人的にはブリットポップのバンドを思い出す)説明すると、ある要素からフォーカスが外れた際に(別のところをクリックするなど)発生するイベントのこと。
要はblur(ぼやけるの意)がfocusの対義語だから、フォーカスアウトするイベントをそう呼んでいるらしい。

blurイベントを使用した例
// 前掲例のchangeをblurに変えただけ
document.getElementById("DateUntil").addEventListener("blur", dateUntilChanged);

Chromeでは、デートピッカーを抜け出しただけではblurイベントが発生しないので注意!
(<input type="date">の年の部分が選択されているため)
ほかの箇所をクリックした時点でblurが発火するので、実用上はそこまで問題ではない。
私が使った場面は<form>で検索期間を指定して「検索」ボタン押下というシナリオだったので、この問題は無視できた。

おさらい(CodePen)

See the Pen Javascriptで日付の連動更新をする by Nagayama Toshiaki (@NagayamaToshiaki) on CodePen.

参考文献

holstetoさんの回答(英語)
javascript - HTML5 <input type=“date”> - onChange Event - Stack Overflow

<input type="date">が変更された際に発生するイベントについてまとめられています。
この回答に出会わなければこの記事を書けませんでした。

追記

Firefox 78でも同様の挙動が確認できたので、一部取り消し線を入れました。

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

Google タグマネージャーで子孫要素のクリックイベントもきっちり検出する

Google タグ マネージャー (以下 GTM と表記)にはクリックイベントを検出するためのトリガータイプとして「すべての要素」と「リンクのみ」の二種類が用意されています。「すべての要素」を利用するとリンクだけでなくボタンやフォームなどの要素もターゲットに指定することができますが、ターゲットの子孫要素のイベントは検出してくれません。

この仕様は Google Analytics (以下 GA と表記)などの外部サービスにクリックのイベントデータを送出するといったユースケースで問題となる可能性があります。例えば以下のような HTML において <button> をイベントターゲットに指定した場合、子要素の <i> がクリックされてもトリガーはそのイベントを検出しません。

<button>  <!-- button 要素のクリックは検出される -->
  <i class="material-icons">close</i>  <!-- icon 要素のクリックは検出されない! -->
</button>

この記事では、子孫要素のクリックイベントも含めてターゲットのイベントとして扱う方法について考えてみます。

TL;DR

  • トリガーの発生条件に CSS セレクタでターゲット要素とその子孫要素の両方を指定する。
  • カスタム JavaScript の変数として、クリックされた要素に最も近いターゲット要素(の属性値など)を返す関数を作成する。

シチュエーション

GTM を経由して、クリックイベントをトリガーに GA へイベントデータを送出するシチュエーションについて考えます。例えば以下のような HTML について考えます。

<body>
  <a href="https://example.com/products/999"
     target="_blank"
     data-tracking-category="product-list"
     data-tracking-action="click-product"
     data-tracking-label="thumbnail">
    <div class="thumbnail-wrapper">
      <p class="product-name"></p>
      <img class="thumbnail" src="thumbnail.jpg">
      <div class="logo-wrapper">
        <img class="logo" src="logo.jpg">
      </div>
    </div>
  </a>
</body>

ここで GTM のコンテナスニペットは省略しています。

ターゲット要素に data-tracking-category といった属性を仕込んでおき、この値によってどの要素がクリックされたか識別できるようにしています。 GA のイベント要素については公式のヘルプページを参照してください。

Google Tag Manager の設定

トリガー

まず data-tracking-category を属性に持つ要素、およびその子孫要素のクリックイベントを検出するトリガーを作成します。今回は Click - Data Tracking という名前にして、以下のように設定します。

  • トリガーのタイプ: 「クリック - すべての要素」
  • このトリガーの発生場所: 「一部のクリック」
  • イベント発生時にこれらすべての条件が true の場合にこのトリガーを配信します:
    • 「Click Element」
    • 「CSS セレクタに一致する」
    • [data-tracking-category], [data-tracking-category] *

[data-tracking-category] でターゲット要素を、 [data-tracking-category] * でその子孫要素をそれぞれ取得することができます。

変数

次にクリックされた箇所の data-tracking-category などの値を格納する変数を作成します。通常、トリガーによって検出されたイベントの発生した要素(ここではクリックされた要素)の情報は「自動イベント変数」を使って取得することができます。ただし今回の場合、子孫要素がクリックされた場合に親の data-tracking-category を取得する必要があり、「自動イベント変数」ではこれを実現できません。

この問題の解決方法について Simo Ahava さんのブログ記事を参考にさせてもらいました。まず utility 関数として Find Closest という変数を作成します。

Find Closest
function() {
  return function(target, selector) {
    while (!target.matches(selector) && !target.matches('body')) {
      target = target.parentElement;
    }
    return target.matches(selector) ? target : undefined;
  }
}

この変数では引数 selector に渡された CSS セレクタに一致する要素が見つかるまで target から再帰的に親要素を辿ります。この引数に [data-tracking-category] を指定することで、 data-tracking-category 属性を持つ親要素が取得できるという寸法です。

実際に data-tracking-category の値を取得する変数を Closest Data Tracking Category という名前で以下のように作成します。

Closest Data Tracking Category
function() {
  var el = {{Find Closest}}({{Click Element}}, '[data-tracking-category]');
  return typeof el !== 'undefined' ? el.getAttribute('data-tracking-category') : undefined;
}

{{Click Element}} は GTM の組み込み変数で、名前の通りクリックされた要素が格納されます。
これと同様に Closest Data Tracking ActionClosest Data Tracking Label も作成しておきます。

タグ

最後に GA に情報を送るためのタグを作成します。

  • タグの設定
    • タグの種類: 「Google アナリティクス: ユニバーサル アナリティクス」
    • トラッキング タイプ: 「イベント」
    • カテゴリ: {{Closest Data Tracking Category}}
    • アクション: {{Closest Data Tracking Action}}
    • ラベル: {{Closest Data Tracking Label}}
  • トリガー
    • Click - Data Tracking

その他 GA の設定などは環境に合わせて適宜行ってください。

動作確認

最後にプレビューモードで動作確認します。トラッキングしたい要素およびその子孫要素をクリックし、イベントが発火すること、変数に目的の値が設定されていることが確認できればオーケーです!

!

!

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