20190716のCSSに関する記事は11件です。

46日目、VW で画面のサイズでフォントや画像のサイズを変える

46日目。Javascriptで配列を作ってまとめて更新、メンテしやすくなりました。

続きです。

画面のサイズで横幅を変える

画面の横幅を基準にする「vw」で画像やフォントの大きさを設定してみました。
ブラウザを伸ばしたり縮めたりすると図と文字がのびたり縮んだりします。おもしろーい!

CSSのfont-sizeが%とかemとかremとかvwで指定されてると、ビビっちゃう君と僕を救う2分

test.css
.main {
  width:100vw;
  padding: 1em;
  }

.contents { 
  width: 100vw;
  height:15vw;
  }

.contents img {
  width:12vw;
  height:12vw;
  margin:0em 1vw;
}

.left { 
  float:left;
  margin-right:1vw; 
}

.center{
  float:left;
  width:70vw;
  height:12vw;
  background-size:cover;
  background-image: url(cat.png);
}

.right {
  float:right;
  }

リストの先頭文字をなしに。

test.css
li {
  list-style: none;
  color:white;
  }

フォントは明朝体にしたい。

どの環境でも綺麗なゴシック体、明朝体のフォントを指定する

test.css
font-family: "游明朝", YuMincho, "ヒラギノ明朝 ProN W3", "Hiragino Mincho ProN", "HG明朝E", "MS P明朝", "MS 明朝", serif;   

要素のセルいっぱいに背景画像を表示したい。その上に文字を表示したい。

トップページ  > CSS3  > background-size

.center{
  float:left;
  width:70vw;
  height:12vw;
  background-size:cover;
  background-image: url(cat.png);
}

ProgateのHTML & CSS 初級編

復習しながらCSSを組み立てました。
学習コース HTML & CSS 初級編

完成!

HTML & CSS 初級編とVWだけでできています。
拡大縮小するとずれまくるし、画像は飛んでいくしなかなか大変でした。

所要時間 5時間

・HTML & CSS 初級編 1時間
・CSS組み立て
 1回目、pxで1時間
 2回目、vwで1時間
 3回目、画面を細長くしたときに要素が崩れるので組み直し 2時間

ここまで11時間。
かかってるなー!!!

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

HTML の インライン要素 インラインブロック要素 を 画面(親要素)の中央 に 表示する

目的

  • HTMLファイルのブロック要素を画面(親要素)の左右の中央に配置する設定するをまとめる

押さえるポイント

  • インライン要素・インラインブロック要素の配置位置を指定するにはtext-alineプロパティを使用する。
  • 要素の位置は中央の他に左側、右側も指定できる。
  • 要素の位置はcenter(中央)、left(左側)、right(右側)で指定する。
    ※ブロック要素を中央に配置する設定はこちらに記載しています。

書き方の例

  • 下記にCSSファイルの内容を記載する。
要素の名前かクラス名 {
  text-aline: 要素の配置場所の指定;
}

より具体的な例

  • a要素の位置を画面左右中央に配置する。
  • input要素の位置を画面左側に配置する。
  • textarea要素の位置を画面右側に配置する。
  • 下記にHTMLファイルの内容を記載する。
<a>Googleへ</a>
<input>
<textarea></textaria>
  • 下記にCSSファイルの内容を記載する。
*/ 中央配置 /*
a {
  text-aline: center;
}

*/ 左側配置 /*
input {
  text-aline: left;
}

*/ 右側配置 /*
textaria {
  text-aline: right;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTML の 文字 の 太さ を 設定する

目的

  • HTMLファイルの文字の太さを設定する方法をまとめる。

押さえるポイント

  • 文字の太さを設定するにはfont-weightプロパティを使用する。
  • 文字の太さはfont-weightにて細字にしたい時はnormal、太字にしたい時はboidを設定する。
  • h1〜h6はデフォルト値でboidが設定されている。

書き方の例

  • 下記にCSSファイルの内容を記載する。
要素の名前かクラス名 {
  font-wight: 字の太さの指定;
}

より具体的な例

  • h1要素の文字の太さをnormalに設定する。
  • p要素の文字の太さをboidに設定する。
  • 下記にHTMLファイルの内容を記載する。
<h1>おはようございます。</h1>
<p>これは日本の朝の挨拶です。</p> 
  • 下記にCSSファイルの内容を記載する。
h1 {
  font-weight: normal;
}

p {
  font-weight: boid;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

HTML の リンク の クリックできる範囲 を 広げる

目的

  • HTMLファイルの行間の高さを設定する方法をまとめる。

押さえるポイント

  • リンクを作成するaタグはインライン要素のため文字部分しかクリックできる範囲がない。
  • クリックする範囲を広げるにはaタグをインライン要素からブロック要素に変えてあげる
    ※HTMLでのリンクの作成方法はこちらを参考にしてください。

書き方の例

  • 下記にCSSファイルの内容を記載する。
要素の名前かクラス名 {
  display: block;
}

より具体的な例が思いつかなかったため今回は記載しない。

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

HTML の 行間 の 高さ を 設定する

目的

  • HTMLファイルの行間の高さを設定する方法をまとめる。

押さえるポイント

  • 行間の高さを設定するにline-heightプロパティを使用する。
  • 行間の高さはピクセル数を用いて設定する。
  • line-heightで行間の高さを設定すると、テキストは設定した行間の縦方向の中央に勝手に配置される。

書き方の例

  • 下記にCSSファイルの内容を記載する。
要素の名前かクラス名 {
  line-height: ピクセル数;
}

より具体的な例

  • h1要素の行間の高さを10ピクセルに設定する。
  • 下記にHTMLファイルの内容を記載する。
<h1>おはようございます。</h1>
  • 下記にCSSファイルの内容を記載する。
h1 {
  line-height: 10px;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ついてくるヘッダーを簡単に作る。

<!-- 省略 -->
<style>
body { z-index: 0; margin: 0; pasding: 0 }
#header { position: fixed; top: 0; left: 0; z-index: 100 }
</style><!-- CSSでかぶるところがあってら消してください -->
<script src=//code.jquery.com/jquery-3.3.1.min.js></script><!-- jQueryをすでに読み込んでいる場合は不要です -->
<script>
$(function() {
  $('body').css('padding-top',$('#header').outerHeight());
});
</script>
</head>
<body>
<header>
<div id=header>
<!-- 省略 -->
</div>
</header>
<!-- 省略 -->

間違ってたらごめんなさい。


7/17 追記

一応解説しときます。
最初にstyle要素のz-indexでbodyの上に#headerを重ねてposition:fixed;で画面上部に固定。
jQueryで#headerの高さを取得してbodyにpadding-topをその分だけあててます。
やっぱり間違ってたらごめんなさい。

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

Progate HTML/CSS 初級編①

はじめに

未来電子テクノロジー(https://www.miraidenshi-tech.jp/intern-content/program/)
で、インターンをしているたくみです。
今回は先日取り組んだ Progate HTML/CSSの初級編の一部をまとめてみました。

HTML要素

* 見出しの作り方

見出しを作りたいときには以下のように記述する。

<h1>________</h1>

見出しの大きさを変更したいときは"h"の後の数字を変える。

<h1>________</h1>
<h2>________</h2>
<h3>________</h3>

* リンク設定

リンク設定をしたいときには以下のように記述する。

<a>________</a>

リンクを指定したいときは"a"の後に以下の記述を加える。

<a href="リンク名">________</a>

* 段落設定 

段落設定は以下のように記述する。

<p>________</p>

* 画像の挿入

画像の挿入は以下のように記述する。

<img src="画像のリンク">


* リストの作成

リストの作成をしたいときには以下のように記述する。

<ul>
  <li>_______</li>
  <li>_______</li>
</ul>

おわりに

プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。

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

CSS設計手法「FLOCSS」を適用して出てきた疑問を自分なりに考えて進めた結果と得た知見と失敗と

1. はじめに

本記事は普段業務でサーバサイドをやっている筆者が、フロント知識ほぼゼロから独学で勉強を進めながらポートフォリオ制作を始め、素人ながらもCSS設計手法「FLOCSS」を適用して得た知見等を記す。
本題のFLOCSSの話の前に、読むうえで必要になりそうな知識(CSS設計手法/HTML/CSS等)+αも2~4章にまとめているため必要がある方のみ読んで頂ければと思う。必要ない方は5章(FLOCSSの話)まで飛ばして頂ければと思う。
本章では、FLOCSSを適用するに至った経緯を記す。

1.1. CSS設計手法を知ったきっかけ

ポートフォリオ作成に取り掛かり始めた頃のある日にtwitterのTLでふいに流れてきた以下記事がきっかけである。(感謝の言葉しかありません)

【参考記事(Qitta)】

各CSS設計手法を取り入れる上でのメリット・デメリットをまとめてみた

1.2. CSS設計手法の導入を決めた理由

CSS設計手法を使わずに我流な書き方にて1頁分CSS(Sass)を作成してみた結果、このまま作成を続けると以下のようなコードになってしまうと悟った。

  • コード共通化が上手くできず、コピペで同じコード量産(効果的なやり方が分かっていない)
  • 1ファイルのコード量肥大化(ファイルの適切な分け方が分かっていない)
  • 後から一部修正すると思わぬ箇所に影響が及ぶコードができあがりそう(詳細度、組み合わせの管理破綻)

そのため、なにかしらの設計手法を適用し、(設計手法の理解が足らず100%準拠はできなかったとしても)ある程度メンテナンス性を確保する必要があると考えた。

2. CSS設計手法について

2.1. 各CSS設計手法の概要

CSS設計手法についていくつか簡単に紹介する。詳細は参考サイトをご参照。

■ OOCSS(Object Oriented CSS)
オブジェクト指向にもとづいて考案された設計思想

■ BEM(Block Element Modifier)
独特な命名規則「MindBEMding」からなる設計思想。「.Block__Element--Modifier」という命名ルールに従いクラス名を決定。

■ SMACSS(Scalable and Modular Architecture for CSS)
OOCSSやBEMの流れをうけて考案された設計思想。BEMより緩い命名規則と、OOCSSのようなマルチクラス設計が特徴

■ MCSS(Multilayer CSS)
OOCSSとBEMの原理を基に作成された設計思想。CSSモジュール(及び、その内部ブロック)をレイヤー毎に分離し、各レイヤー上から順に重ねるイメージ。

■ SuitCSS
コンポーネントベースの設計手法。BEMに加えて汎用クラスを利用する。

■ FLOCSS
上記の設計手法の良い所取りをした設計手法

以下、各設計手法についての参考及び引用元サイト
OOCSS、BEM、SMACSS、FLOCSS、RSCSSを比較して自分にあった設計思想をみつける
各CSS設計手法を取り入れる上でのメリット・デメリットをまとめてみた
より良いCSSを書くための様々なCSS設計まとめ
SUIT CSS
CSS設計を学ぼう

2.2. FLOCSSを選択した理由

以下の理由から、SMACSS、MCSS、FLOCSSに絞り込んだ

  • (個人開発のもののため)規模が大きくはないこと
  • オブジェクト指向に慣れ親しみがあるので、OOCSSを取り入れたい
  • 我流で書いていたやり方がレイヤ毎に分ける手法に近いため、馴染むのに大きなコストはかからない(はず)

絞り込んだ3つの中で最初はMCSSを選択した。理由は「CSS設計に慣れてない人でも理解はしやすい」ことがメリットとしてあり、CSS設計素人の自分でもできると推測したため。
しかし、MCSSを適用して書いたコードを書き換えようとすると、(ググっても参考になるものがあまり出てこなかったこともあり)書き方が分からず詰まった。このまま進めてもスピード感が出ないと判断して、MCSSも選択肢から除外することとした。

情報量という点についてはMCSS以外はどちらも十分と判断し、FLOCSSには「Component にするか Project にするかで迷う」という素人には重荷になりそうなデメリットがあるため、順当に考えればSMACSSが良いかと考えた。しかし、最終的に「学習の幅がある」「挑戦」という面を重視して以下の理由からFLOCSSを選択した。

  • FLOCSSは、SMACSSの考え方も含むため、FLOCSSをやってもSMACSSの考え方をある程度は学べる。
  • 可能ならば自分なりの見解を出せるような挑戦要素が欲しいと考えていたため、以下2点に挑戦要素があると考えた。
    • デメリットの「Component にするか Project にするかで迷う」という点
    • 割と新しめの設計手法である点
  • デメリットの「Component にするか Project にするかで迷う」点について、最悪できなかったとしても、ComponentとProjectに分けなければ自分でもできると判断したため。(そうしても、SMACSSより1レイヤ分少なくなるため、管理もしやすいと考えていた。結局ComponentとProjectは分けて最後まで通した。)

3. FLOCSSとは

FLOCSSでは大きく以下の3つの層に分けて管理する(Object層にはさらに3つの子レイヤーに分かれる)。命名規則には、MindBEMdingを採用している。

・Foundation : normalize.cssなど
・Layout : レイアウトのスタイル
・Object : コンポーネントのスタイル
 ・Component : 再利用可能なコンポーネント
 ・Project : プロジェクト毎のスタイル
 ・Utility : clearfixやmarginなどの小さなスタイル

詳細は以下、公式サイトをご参照。

公式ドキュメント:https://github.com/hiloki/flocss
公式設計デモ:https://github.com/tacrow/flocss-demo

4. 本題の前に押さえておきたいHTML/CSS基礎知識+α

HTML/CSSもほぼ1から学習したため、個人的にまとめておきたい点をまとめておく。

4.1. HTMLはブロック構造で考える

HTMLを書く際は、「ブロック分け」が重要なキーになり、レイアウトするために過剰にCSSを書くようなことも防げる。

※詳細は以下サイトがとても参考になると思われるので必要な方はご参照されたし。

参考サイト:CSSができる人とできない人では何が違うのか?(レイアウト編)

本記事でも以下に例を載せる。
(左:HTML/CSSで実装したサンプル、右:実際のHTML上のブロック分け)
HTMLブロックサンプル2.png

4.2. レスポンシブなレイアウトに頼もしいFlexBox/GridLayout

FlexBox、GridLayoutについて簡単にまとめる。

FlexBoxは、柔軟なレイアウトを実現可能。
FlexBoxの基本的な使い方は以下サイトが参考になると思われるのでご参照されたし。

参考サイト:css display flex の 使い方(中央寄せなど)

GridLayoutは、行と列を持つグリッドベースのレイアウトが可能。
GridLayoutの使い方は以下記事が参考になると思われるのでご参照されたし。

参考Qiita記事1:CSS Grid Layout を極める!(基礎編)
参考Qiita記事2:CSS Grid Layout を極める!(場面編)

レイアウトを調整する際は、Floatも含めて使い分けが重要である。
以下サイトが参考になると思われるのでご参照されたし。

FlexBox/GridLayout/Float使い分け参考サイト:
特徴で使い分けたいCSSレイアウト手法

レスポンシブレイアウトを実現するために、メディアクエリを使用するが、FlexBoxやGridLayoutだけでレスポンシブなレイアウトにすることも可能である。

参考サイト:CSS GridとFlexboxを使ってメディアクエリなしでレスポンシブにレイアウトする方法

※蛇足
上記参考サイトだと、FlexBoxやGridLayoutを適用したブロック内の要素のサイズも画面幅に応じて変化してしまうので、メディアクエリとGridLayoutを組み合わせてブロックの幅のみ画面幅に応じて変化し、ブロック内の要素のサイズは固定となる例を作ってみた。

サンプル:https://sympathia.hatenablog.com/entry/2019/06/08/011613

4.3 SassというCSSをプログラミング言語のような書き方ができる便利な形式

Sassとは、CSSをプログラミング言語っぽく書くことができるメタ言語(ある言語について何らかの記述をするための言語)である。HTML/CSSはあまり触ったことないがCやJava等なにかしらプログラム言語に触れたことがあるという方にはとっつきやすい。

・変数定義

$fontColor = #333;
$baseWidth = 960px;

・親子関係

.parent {
  width: 100px;
  p {
    font-size: 16px;
  }
}
// 実際に生成されるcss
// .parent {
//   width: 100px;
// }
// .parent p {
//   font-size: 16px;
// }

・継承

%box{
  width: 100px;
  height: 100px;
}
.color {
  background-color: bule;
}

.block{
  @extend %box;
  @extend .color;
}
// 実際に生成されるCSS
// .block {
//   width: 100px;
//   height: 100px;
//   background-color: bule;
// }

・関数化

@mixin grad($start: red, $end: blue){
  background: liner-gradient($start, $end);
}

.mixSample1{
  @include grad();
}
.mixSample2{
  @include grad(green, yellow);
}
//実際に生成されるCSS
// .mixSample1 {
//   background: liner-gradient(red, blue);
// }
// .mixSample2 {
//   background: liner-gradient(green, yellow);
// }

など、他にも色々できる。
ちなみにSassにはSASSとSCSSの2種類あり

・SASS記法(VBA/Ruby/Pythonなどと同じ書き方)

.class
  width: 100px;

・SCSS記法(C/Java/JS/PHPなどと同じ書き方)

.class {
  width: 100px;
}

4.4 要素の縦/横/中央揃えは良く使ったので押さえておいて損はない

ググるといくつか方法が見つかるが分かるまでは使い分け方がよく分からなかったため簡単にまとめておく。

(1) インライン要素 横方向中央寄せ

p {
  text-align: center;
}

(2) インライン要素 縦方向中央寄せ

// この方法だと2行以上に渡るテキストに対しては使えない
.parent {
  height: 100px;
}
.parent p {
  line-height: 100px;  //親要素のheightと同じ値にする
}

(3) ブロック要素 横方向中央寄せ

.block {
  margin: 0 auto;
}

(4) インライン要素/ブロック要素共通 縦方向中央寄せ

.parent {
  height: 200px;
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  transform : translateY(-50%);
}

(5) インライン要素/ブロック要素共通 中央配置

.parent {
  height: 200px;
  position: relative;
}
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform : translate(-50%, -50%);
}


以下は、FlexBoxとGridLayoutを使用した場合の例である。
(6) Flexboxを使用した中央配置

.parent {
  display: flex;
  justify-content: center; //横方向中央寄せ
  align-items: center;     //縦方向中央寄せ
}

(7) GridLayoutを使用した中央配置

.parent {
  display: grid;
  grid-template-columns: 100px;
  grid-template-rows: 100px;

  .child {
    justify-self: center;  //横方向中央寄せ
    align-self: center;    //縦方向中央寄せ
  }
}

詳細は以下のサイトをご参照されたし

参考サイト1:CSSで中央寄せする9つの方法(縦・横にセンタリング)
参考サイト2:[CSS]要素を上下左右の中央に配置、最近主流になっている実装方法のまとめ

5. 本編:CSS素人がFLOCSSを試してみて出た疑問と知見と失敗と

FLOCSSを適用して詰まった点、悩んだ点、考えたこと、気付き事項などをまとめておく。

5.1. Layout層とObject層の境界すら迷子になった件

境界が迷子になる事案が主に2点あった。

(1) FLOCSSを取り入れた当初は、Layout層とObject層の境界の基準が良く分からなかった。
これを解消するのに、以下のイメージが役立った。

イメージ図引用サイト:FLOCSSを扱いきれないあなたに贈る、スリムなCSS設計の話
image.png

Layout層で、以下の図のように頁全体のレイアウト決め(土台となるブロックへの分割)を行えばよいかと考える。
レイアウト.png

(2) Layout層とObject層が重なったり、Objectの中にLayoutが入り込むケースがある
project層のブロック内の要素を横並びにしたい場合に、display:flexを使うとする。これは様々な箇所で良く使うので以下のように共通化するとして、「プロジェクト共通の(コンテナー)ブロックのスタイル」はLayout層なので、以下のようにしてみる。

.l-flex {
  display: flex;
  flex-flow: column;
  justify-content: space-around; //均等配置
}

そうすると、以下のようにLayoutとprojectが重なったり、Object層の中にLayoutがある状態になるケースが出てきた。

(例1)

<div class="l-main">
  <div class="l-flex p-block">
    <div class="p-block__element1"></div>
    <div class="p-block__element2"></div>
    <div class="p-block__element3"></div>
  </div>
</div>

(例2)

<main class="l-main">
  <div class="p-block">
    <div class="l-flex p-block-sub">
      <div class="p-block-sub__element1"></div>
      <div class="p-block-sub__element2"></div>
      <div class="p-block-sub__element3"></div>
    </div>
  </div>
</main>

これに関しては、(人の趣向等により)管理方針が以下3つ程上げられるかと考える。
※筆者は、display:~は一律Layout層内だけに存在するようにし、それをどこに適用しているか俯瞰して見れた方が良いと考えたため、②で管理することとした。

① Layout層ではなく、utility層で定義する
② 上記の例のように、Layout層としてhtmlに記述する(l-flexのような共通スタイルは、idがhtml内で1度しか使えないのでclassで定義せざるを得ない)。
③ cssにて、使用するObjectに対して継承する(例は以下を参照)。

// (例1)の場合
.p-block {
  width: 90%;
  @extend .l-flex;
}
// (例2)の場合
.p-block-sub {
  font-size: 20px;
  @extend .l-flex;
}

5.2. 後から気付いたLayout層はこうすれば良かった説

レスポンシブ対応とGridLayoutの使いどころを押さえるのを後回しにしていために起きた悲劇を紹介する。

GridLayoutはある程度自由にブロック分けできるので、以下図のようにGridLayoutで表示するコンテンツの各領域となるブロックに分ける、というのをLayout層で行うのが賢いやり方だと後から気付いた。
(筆者はGridLayoutを使わずに以下図のようなレイアウト調整を行ってしまった)

レイアウトgrid.png

5.3. やはりProject層とComponent層の分類が曖昧になった件

公式のサンプルを見ているproject層とcomponent層の分け方には、以下のパターンが見受けられた。

(1) project層の中にproject/component

<div class="p-block">
  <div class="c-heading"></div>
  <div class="p-block-body">
    :(略)
  </div>
</div>

上記例の".p-block-body"の中にまたproject/componentがある構造となっているようなものもあった。

(2) project層のelementをcomponentに合わせる

<div class="p-block">
  <input type="button" class="p-block__element c-button" />
    :(略)
</div>

FLOCSSでは、各層のモジュールを独立させることで再利用性を保つようにしているが
Project層がComponent層のモジュールを変更することだけは許容している。上記の例のようにすることで、CSSの優先度により、".c-button"のスタイルを".p-block__element"で上書きする(変更する)ことができる。

(3) projectもcompoentも別々

<div class="p-block">
  <div class="p-block__element">
     :
  </div>
</div>
<div class="c-media">
  <div class="c-media__element">
     :
  </div>
</div>

上記例のように最小単位のボタン等の部品をいくつか含むブロックをcomponentとするケースもあるようだが、そうすべきケースまでは分かっていない。最小単位をどう定義するか次第だと考える。

projectとcomponentの分け方の考えた方については以下記事が参考になるかと思われる。

参考サイト: FLOCSSを使ったCSS設計での悩みどころと解決案

以下、自分でこうすればよいか?と考えたproject層/component層の分け方の独自方針について記述する。
主な方針は以下の通りとした。

  • 部品を使用するページや媒体(PC,タブレット,スマフォ等)が変わっても、スタイルを変えないプロパティ(または基準とするプロパティ)はcomponentに配置
  • 逆に変える必要があるプロパティ(またはcomponentで定義した基準を上書いて変更するプロパティ)はprojectに配置

こうすることで、Objectを別のページで使用する場合(スタイルの変更が必要なケース)やレスポンシブ対応のためにメディアクエリでコードを書く際に、componentはそのまま使用でき、projectだけ既に書いたコードを流用しつつスタイルの値を修正するだけで済むので実装がしやすくなると考えたためである。
デメリットとしては、projectとcomponentがセットで扱うことを意識する必要があること(projectとcomponentのどのクラスが結びついているか名称やコメントで管理せざるを得ない、projectのクラスにcomponentのクラスを継承(extend)して管理した方がよいかもしれない)。

<div class="c-article p-article">
  <div class="c-article__img p-article__img"></div>
  <div class="c-article__title p-article__title"></div>
  <div class="c-article__date p-article__date"></div>
</div>
.p-article {
  width: 150px;
  height: 200px;
  margin: 5px;

  .p-article__img {
    width: 150px;
    height:100px;
  }
  .p-article__title {
    height: 80px;
    display: flex; 
  }
  .p-article__text {
    line-height: 18px; //行間の幅指定
  }
}

.c-article {
  background-color: white;
  border: 1px solid #333;

  .c-article__img {
    margin: 0 auto;  //横中央揃え
  }
  .c-article__title {
    font-size: 16px;
    text-align: center;
  }
  .c-article__text {
    font-size: 13px;
    text-align: center;
  }
}


もしもproject層とcomponent層は分け方が分からない場合かつ作成物のデザインが複雑でない、規模が大きくないならば、無理に分けずにまずはProject層とComponent層を1つの層(例えばObject層)としても良いと思われる。

5.4. 実はObject層のProjectとUtilityの分け方も若干迷った件

marginとpaddingは、ブロックの外側または内側の余白を作るためのスタイルで、公式ではutilityになっているように取れる(「Object自体が持つべきでない」がどこまでか線引きが曖昧なため)

Object自体が持つべきではないmarginの代わりに.mbs { margin-bottom: 10px; }のようなUtility Objectを用いて、隣接するモジュールとの間隔をつくるといった役割を担います

(HTMLとCSSを並行して作成していた可能性もあるが少なくとも)要素に対するmarginとpaddingに関しては、project層に配置する方が管理しやすいと感じた。理由は以下の3つである。

  • サイズ調整/修正がしやすかった(微調整のためにHTML(下部例のようなケースだとclassのu-mg-tb5を変更要)とCSS(下部例のようなケースだと.p__btnの幅/高さや位置を修正要)を行ったり来たりする必要があるので非効率に感じた)。
  • HTMLに書くとレスポンシブ対応を考えた際に融通が利かずutility層の汎用性が落ちる(端末毎で要素間のmarginを変える場合、下部例だとutitlity層のクラスにメディアクエリを適用する必要が出てくる)
  • 以下のようなケースの場合に、htmlに書くとコードが冗長だと感じてしまう

例(画面表示/HTML/CSS):
ボタンs.png

<div class="l-flex p-block">
  <div class="p-block__btn c-btn u-mgn-tb5">ボタン1</div>
  <div class="p-block__btn c-btn u-mgn-tb5">ボタン2</div>
  <div class="p-block__btn c-btn u-mgn-tb5">ボタン3</div>
  <div class="p-block__btn c-btn u-mgn-tb5">ボタン4</div>
</div>
.mgn-tb5 {
  margin: 5px 0; //上下5px
}
// Layout層、Project層、Component層は省略

以上からmarginとpaddingはProject層に入れてもいいのではと考える。前述の通り、以下のようにすることでproject層のファイルを見るだけで、要素のサイズに対するプロパティを集約できる(個人的には以下例のようにmarginのプロパティのみ定義しているクラスを継承しても、そのクラスの内容を確認するためにUtility層のファイルを見る必要があり可読性が落ちるため、marginのプロパティを直接記述した方が良いと考える)。

.p-block {
  width: 50px;
  @extend .u-mgn-tb5;  //もしくは margin: 5px 0; と記述してしまう
}

5.5. 最終的にUtility層はスカスカになった件

筆者がプログラミング経験者のため、コーディングの際に不要なものは実装しないという固定観念から必要なスタイルのみを実装したが、公式のサンプルを見ると必要/不要に関わらず何パターンも実装していた。

// margin
.u-m0 {
    margin: 0;
}
.u-m1 {
    margin: 1px;
}
.u-m2 {
    margin: 2px;
}
.u-m3 {
    margin: 3px;
}
.u-m4 {
    margin: 4px;
}
.u-m5 {
    margin: 5px;
}
// 以下続く

上記のようにすることで、他のWebサイトを新規に作成する際にもそのままUtility層のファイルは流用できる。
そのため、必要になりそうなものは事前に実装した方がよいと考える。

※ただ、(Sassファイルから生成される)CSSファイルに、実際には使用していないクラスも含まれてしまい、ブラウザで表示する際に、HTML上の各要素に使用されているクラスをCSSファイルから検索する際に検索する母数が増えるので表示速度が落ちるではないか?(HTML/CSSを読み込んでブラウザに表示する際の詳細な仕組みまで押さえれていないため前提が間違っていたらすみません)それなら、使用しないクラスをCSSファイルに入れないよう工夫した方が良いと考えるが、それを実現する方法をすぐに思い付かなかったため割愛

5.6. ファイルの分け方を誤ってしまった件

以下図のように、概ねLayout層でブロック分けしている領域毎に対応するようProject/Component層のファイルを作成した。

ファイル名.png

Component層は類似部品ベースでファイルを分けるべきであった。複数頁に渡って共通で使用できる部品が少なかったため問題とまではいかないものの再利用性に欠ける部分があるのは否定できない。こうなった理由は次節で述べる。
またLayout/Project/Component層で同じ名前のファイルが存在したため、編集しているファイルがどの層のものか常に確認しながら行うという手間が発生したため、ファイル名はどの層のものか一目で分かるように工夫した方が良いと思う。

5.7. うまく行かなかった要因の1つは最初から基本的な進め方から反れていたから説

実装の際、ある程度しっかり作ったデザインを基に、HTMLを少し書く→そこに対応するCSSを記述、といった具合にHTMLとCSSを交互に少しずつ作成していった。HTML/CSS実装経験がなかったため、どう実装すれば思い通りの配置になるかイメージできなかったため、確認しながら進めたからである。(そのためスピードも出なかった)

本来は、以下作業は分けて行うのかと思う。
・HTML実装
・CSS設計
・CSS実装

デザインを見て、HTMLのブロック構造をどうすればいいかイメージできれば、上記の作業を1つずつこなせるかと思う。前述の通り、経験値がないためHTMLのブロック構造をイメージできず、上記作業を並列に行ったためにそれがファイルを適切に分けられなかった一番の要因に繋がったと考える。

5.8. 設計手法に曖昧な部分があるからこそ管理しやすいように独自ルールを考えてもいい説

調べる中で、いくつか拝見したが、開発を行いやすくする目的で独自のルールを導入するケースが見受けられた(なので、自分も管理しやすくする目的で5.3節で紹介した独自ルールを考えてみた)。
これらの先人達の手法の中から個人もしくはチームで作成する物に合ったルールを探してみるのもよいと考える。

・他設計手法にもあるレイヤーを増やすのもあり

参考:CSSの設計 – FLOCSSをベースにしたファイルの構成と命名規則を考える

・独自のレイヤーを追加する

参考:【CSS設計】FLOCSSを導入してみて気づいた8つのポイント

・細部に独自のルールを追加する

参考:FLOCSSベースのオレオレCSS設計の紹介

6.最後に

HTML/CSSをほぼ1から学習し、CSS設計手法「FLOCSS」を適用して出くわした問題や失敗内容についてまとめた。FLOCSS及びポートフォリオ制作に関しての個人的な今後の課題は以下の通りである。

・Compoent層とProject層の分け方
公式ドキュメント作成者が執筆した以下の本があるため、こちらも読んで勉強する必要がある。

【PDF版】柴犬でもわかるFLOCSS

・Component層とProject層のファイルの分け方
部品ベースでのファイルを分けるべきであった。ただ、どのページで使用している部品かをある程度把握しやすいようにしておきたいため、どう折り合いをつけるかは検討が必要である。

・命名規則「MindBEMding」について
Block部分の命名の決め方が途中から分からなくなり、独自の命名ルールで進めたため、こちらも要確認。

・CSSフレームワーク(Bootstrap/Fomantic UI等)
(仕事/残業/勉強会参加しながらのためでもあるが)開発スピードが出てないため、スピード向上のため次作品以降はCSSのフレームワークの導入することを検討する必要がある。
有名なBootstrap以外にいくつか存在し、とある勉強会で存在を知ったSemantic UI(現在はForkされてFomantic UIとして開発が進められている)には、Bootstrapより画面分割数が多く、JQuery、React、Vueに対応した版もあるとのことなので試してみたい。

他にも、ポートフォリオ制作に関して以下実装が必要である。
・レスポンシブ対応
・画面の動的処理実装
・画面とサーバサイド間の非同期通信
・サーバサイド実装

最後に、本記事はHTML/CSS/FLOCSSの学習の総集編のようなものにしてしまったため、ボリュームが大きくなってしまった。今後はもう少し小出しにすることを意識したい。
直近はPHP/Laravelの学習とCI/CDの仕組みづくりに取り組むため、次はこれらの記事を何か書ければと思う。

以上。

参考サイト一覧

各CSS設計手法を取り入れる上でのメリット・デメリットをまとめてみた
OOCSS、BEM、SMACSS、FLOCSS、RSCSSを比較して自分にあった設計思想をみつける
各CSS設計手法を取り入れる上でのメリット・デメリットをまとめてみた
より良いCSSを書くための様々なCSS設計まとめ
SUIT CSS
CSS設計を学ぼう
FLOCSS公式ドキュメント
FLOCSS公式設計デモ
CSSができる人とできない人では何が違うのか?(レイアウト編)
css display flex の 使い方(中央寄せなど)
CSS Grid Layout を極める!(基礎編)
CSS Grid Layout を極める!(場面編)
特徴で使い分けたいCSSレイアウト手法
CSS GridとFlexboxを使ってメディアクエリなしでレスポンシブにレイアウトする方法
CSSで中央寄せする9つの方法(縦・横にセンタリング)
[CSS]要素を上下左右の中央に配置、最近主流になっている実装方法のまとめ
FLOCSSを扱いきれないあなたに贈る、スリムなCSS設計の話
FLOCSSを使ったCSS設計での悩みどころと解決案
CSSの設計 – FLOCSSをベースにしたファイルの構成と命名規則を考える
【CSS設計】FLOCSSを導入してみて気づいた8つのポイント
FLOCSSベースのオレオレCSS設計の紹介
【PDF版】柴犬でもわかるFLOCSS
Fomantic UI

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

CSSでひし形の蛍光ペン風の下線を引く方法

最近、CSSでひし形の下線(透過版)を引く事があって意外と難しかったので、忘れないようメモしておく。

簡単に蛍光ペン風の下線を引く場合

通常、CSSで蛍光ペン風の下線を引く際は以下の情報を見る事が多いのではないだろうか。

htmlの記述
<p>募集すると<span class="decorate">反響大</span></p>
css部分の記述
.decorate {
  background: linear-gradient(transparent 70%, #f97b0b 70%);
}

■ブラウザ表示イメージ
old下線.png

ひし形の蛍光ペン風の下線を引く場合

htmlの記述
<p>募集すると<span class="decorate">反響大</span></p>
css部分の記述
.decorate {
  position: relative;
}

.decorate::before {
  background-color: #f97b0b;
  content: '';
  position: absolute;
  bottom: 3px;
  display: inline-block;
  opacity: 0.75;
  width: 75px;
  height: 5px;
  transform:skewX(-50deg);
  z-index: -1;
}

■ブラウザ表示イメージ
下線.png

■解説
・下線の位置を擬似要素beforeで調整するため、spanタグのclassであるdecorateは、
 position: relative;を設定。

・擬似要素beforeを表示する場所として、まずは position: absolute; を設定。

・一部のみ下線を引くため、display:inline-block;を設定。

・下線を表示するため、widthheightbackground-colorcontent: '';を設定。

・蛍光ペン風の色合いを出すため、opacityを設定。

・下線位置を調整するため、 topleftrightbottomを使い、
 今回は bottomのみを設定。

・下線の上に文字が表示されるようにしたいので、z-indexを設定。

・下線をひし形にするため、transform:skewX(-50deg);を設定。
→ transformプロパティのskew(要素を傾斜変形させる)を利用。今回、X軸のみ傾斜させれば良いためskewXを活用。

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

エンジニアだってモックを作りたい(AdobeXDの便利機能とデザインTips)

一人でアプリ作れて、見た目もクールだったら最高ですよね。
一朝一夕ではデザインスキルが身につかないので日々研鑽を重ねる毎日です。

Sketch, Figma などありますが今回は Adobe の XD の使い方を中心に説明し、ダサさが軽減されるTipsについても紹介したいと思います。

はじめに

「Adobe XD なんて使わない」という人は後半にある「デザインチップス」の章だけ見ると良いかと思います。

Adobe XD とは

Adobe 提供するプロトタイピングツールです。
お絵描き出来て、画面遷移を作れて、WEB上で共有してコメントもらったり、開発者にデザインスペックを共有したり出来ます。
このツールは無料で使うことが出来ます。
Qiita内にもいくつも関連記事はありました。

 Adobe XDの基本の使い方
 https://qiita.com/fkana/items/97efdcf49f458a829269

 エンジニアが無料で使える画像編集ツールとしてのAdobe XD入門
 https://qiita.com/furitahiroshi/items/7affdb748eb10e65dbce

不足してる機能もあるかと思いますが、毎月追加され続けてますのでどんどん成長してます。

 Adobe XD アップデート
 https://blogs.adobe.com/japan/serialization/adobe-xd-update/

使い方

Adobe XD には「デザイン」と「プロトタイプ」のメニューがあります。

image.png

  • デザイン: お絵描きする画面
  • プロトタイプ: 画面遷移を設定する画面

画面上にあまりボタン等もないので実際に画面を見てもらえれば使い方に迷うことはあまりないと思いますので、「デザイン」の基本的な使い方は割愛して、画面遷移と便利機能について紹介します。

画面遷移

「プロトタイプ」のメニューから画面遷移を作れます。

例えば、厨二病のための写真共有アプリをデザインしてみるとします。

スマホアプリでよくある、画面を下に引っ張ったら更新される動きを作ってみます。
最終的にはこんな感じのモックアップが作れました。

mov3.gif

画面遷移を作るには、下図のように画面遷移のトリガーとなる対象を選択して次の画面へ繋げるだけです。
繋げた後に、右側の「アクション」を「自動アニメーション」にすると、2画面間の差分を勝手に解釈してくれてアニメーションで補完してくれます。

スクリーンショット 2019-07-13 23.34.12.png

ユーザー操作なしで次の画面へ遷移したい場合は、下図のように「トリガー」を「時間」にします。

スクリーンショット 2019-07-13 23.34.28.png

パラパラ漫画を作っていくような感覚で、画面間を繋いでいくだけで画面遷移やアニメーションを作ることができます。

便利機能:リピートグリッド

これは超便利です。

 公式サイトのリピートグリッドの説明
 https://helpx.adobe.com/jp/xd/help/create-repeating-elements.html

オブジェクトを選択し、右の方にある「リピートグリッド」を選択するだけです。

image.png

それだけで、オブジェクトを繰り返し配置してくれます。

image.png

オブジェクトの間にマウスを持っていくと、リピート間隔の調整もできます。

image.png

これだけでも便利ですが、便利さはまだ留まること知りません。

以下の動画のように、リピートしたオブジェクトに複数の画像ファイルをドラッグ&ドロップすると、良い感じに画像を適用してくれます。

mov1.gif

画像だけでなく、テキストも複数同時に設定することができます。
ちょっと見にくいかもしれませんが、以下の動画はテキストファイルをドラッグ&ドロップしてます。
改行区切りのテキストファイルをドラッグ&ドロップするだけで良い感じで適用してくれます。

mov2.gif

データの流し込みはドラッグ&ドロップ以外にもプラグインを使えば Google のスプレッドシートからデータを流し込みをすることもできます。

 下記記事の「Google Sheets」の部分です
 https://webkikaku.co.jp/blog/software/xd_plugin/

よく使うデータを使い回せるようにしておけば便利そうですよね。

便利機能:コンポーネント

UI部品をコンポーネント化できます。

アトミックデザインのような感じでしょうか。

コンポーネント化は右クリックメニューからできます。

image.png

コンポーネントにしておけば、部品を修正した場合に全部の画面にある部品が同時に修正されます。

以下の動画では、画像アイコンの円に赤縁を後から追加したくなった例です。
手直しが楽になって良いですよね。

mov5.gif

デザインチップス

デザインに自信がない人のためのダサさ軽減Tipsです。
自分はデザイナーではないのでクールな画面を作る方法と言うよりは、マイナスになっているデザインセンスを0に近づけるイメージの内容です。

先ほどの写真共有アプリのプロフィール画面を作り始めてみました。

スクリーンショット 2019-07-13 23.56.45.png

ツッコミどころ満載のプロフィール画面ですがポイントがいくつかあります。

  • 文字色は真っ黒ではない
  • 項目名と値の組み合わせでフォントサイズ、色が違う
  • 単位はフォントサイズを下げる

表のような表示はどんなアプリにもありますよね。
色とサイズをちょっといじるだけで、ダサさが軽減できます。

文字色は真っ黒ではない

文字色は真っ黒(0x000000)よりは少しグレーがかった方がお洒落な気がします。
Adobe XD でもデフォルトの文字色は真っ黒ではありませんでした。

項目名と値の組み合わせでフォントサイズ、色が違う

項目名を少し薄め、主張を減らした方が見やすいと思っています。
特に何度も見るような画面であれば何の項目かはユーザーは覚えるのではないかと思っています。

実際に項目名と値のフォントを全部揃えてみると、さっきの方がまだ良かった気がします。

スクリーンショット 2019-07-13 23.57.57.png

罫線がないのが嫌な人がいるかもしれません。
罫線をつけてみました。

スクリーンショット 2019-07-13 23.57.16.png

罫線も文字色と同じで、真っ黒ではない方がスッキリします。

スクリーンショット 2019-07-13 23.56.53.png

縦の線がない方がよりスッキリするかもしれません。
マテリアルデザインのCSSだと、よく下線だけになってますね。

スクリーンショット 2019-07-14 16.50.38.png

まとめ

「自分の場合はこうやっているよ」という共有でした。

手前味噌ですが似たようなデザイン系の記事で以下も書いてますのでご興味あれば読んでみてください。

 エンジニアだってアートしたい
 https://qiita.com/megumu-u/items/69e65373ddb12d2944f1

 エンジニアが知っておきたい色についてのお話
 https://qiita.com/megumu-u/items/554f3e9f8950ddddb03a

 エンジニアが知っておきたいフォントについてのお話
 https://qiita.com/megumu-u/items/05e6079e75eb1d610d27

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

Vue.jsと<input type=range>でSoundCloudみたいなシークバーを作る

挨拶

こんにちはkaijiです。
最初に、初投稿かつ今までWebをほとんどやったことのない人なので、色々と間違っていたり不足している部分があるかと思います。もしそういった点があった時はコメントで優しく教えてもらえると嬉しいです。

経緯・注意

個人で開発しているサイトでオーディオを再生するためシークバーを実装しようとして色々調べてたのですが、HTML5のAudioタグで作っていたり、inputの標準のUIで作っているものだったり、オリジナルの見た目で作っていてもプログレスバーまで作っているものはほとんど見当たらなかったので、Vue.js上でJavascriptのWeb Audio APIとinputタグを使って自分で作ってみました。
ここでは、シークバーを作ることをメインにしているので、再生、停止、ボリューム調整等の基本的な動作に関しては他のサイトとかを参考にしてください。

全体的な流れ

  1. シークバーの見た目を作る
  2. 実際にシークさせてみる
  3. 現在の再生時間と、全体の再生時間を表示させる(分:秒表示)
  4. 再生済み用のプログレスバーを作り、元のinputタグに重ねる

といった感じです。

シークバーの見た目を作る

シークバーの見た目に関しては、基本好きなように作ってねっていう感じなんですが、いくつか注意点があるので、それについて書きます。

まずinputタグにはデフォルトで見た目が設定されています。(Mac版Chromeの場合はこんな感じ↓)
スクリーンショット 2019-07-15 23.06.19.png
ですが、これだとブラウザごとに見た目が変わってしまったり、サイトによってはデザイン的に浮いてしまうことがあるため(ちなみにこれはHTML5のオーディオタグにも言える)今回は自分でCSSを書いて見た目を作っていくのですが、その前にこのデフォルトの見た目を表示させないように<style>内に以下のCSSを書いてみましょう。

input[type=range] {
    -webkit-appearance: none;
}

input[type=range]::-webkit-slider-thumb {

}

input[type=range]::-ms-tooltip {
    display:none;

}

input[type=range]::-moz-range-track {

}

input[type=range]::-moz-range-thumb {

}

ここではinput[type=range]の見た目を表示させないでくださいと各ブラウザ用に書いています。
こうすることで、真っさらなinput[type=range]ができたので、ここからは実際に見た目を作っていきます。
なぜ-msだけthumbの設定がないのかや、-mozには何も書いていないのか等は以下のページにわかりやすく書かれていたので、そちらを参考にしてみてください。

input type=range タグをカスタマイズするために

実際にシークさせてみる

次は実際にシークをさせてみましょう。
ここではWeb Audio API上でオーディオファイルが再生できる状態になっていることを前提に話をするので、まだ実装できてない人は他の投稿やリファレンス等をみて実装してからもう一度来てください。

今回はVue.jsを使っているので双方向データバインディングのできるv-modelを現在の再生時間、v-bindを全体の再生時間を表示させるために使っていきます。

まず<script>内でオーディオのcurrentTime(現在の再生時間)とdurationTime(全体の再生時間)を取得します。

const audio = new Audio

export default {
    data() {
        return {
            currentTime: 0,
            durationTime: 0
        }
    },

    mehods:{
        play() {
            audio.src = //オーディオのURLとか

            audio.addEventListener("loadedmetadata", function () {
                return {
                    durationTime: audio.duration.toFixed(0)
                }
            });
            audio.addEventListener("timeupdate", function () {
                return {
                    currentTime: audio.currentTime.toFixed(0)
                }
            });
            audio.addEventListener("ended", function () {
                return {
                    currentTime: 0,
                    durationTime: 0
                }
            });
            audio.play();
        },
        seek() {
            audio.currentTime = this.currentTime;
        }
    }
} 

ここでやっていることはaudio.srcで取得したオーディオデータからaddEventListenerを使ってメタデータを抽出できたタイミングでaudio.durationTimeを取得し、その値を返させています。
それと同じように再生中にaudio.currrentTimeを取得しその値を返させています。
また再生が終了したら両方の値を0(初期値)にしています。

そして下に書かれているseek()というメソッドではv-modelの特性である双方向データバインディングを使ってthumbを移動させるたびにその位置(時間)まで実際に再生されている音源のaudio.currentTimeを移動させています。

またaudio.durationTimeaudio.currrentTimeを取得するときtoFixed(0)と書いていますが、これは取得してきた値を整数に変換しています。
なぜこんなことをするのかというと、標準で取得してくる再生時間はミリ秒(1/1000秒)で表されているため、今回作るようなプレイヤーの場合あまり適している形とは言えません。
そのため今回は整数で表すようにしていますが、もし作るプレイヤーがミリ秒まで表示できるものであって欲しいならtoFixed(n)を書く必要はありませんし、toFixed(n)はnの値を変えることによって0.1秒単位(その場合nは1になる)などもっと細かい値にすることも可能なので、自分の用途に合わせて調整してみてください。
詳細は下記のURLから見てください

Number.prototype.toFixed()

では次に<template>内に記述していきます。

<a v-on:click=play>再生</a>
<input type="range" v-model="currentTime" v-on:input="seek" v-bind:max="durationTime"/>

最初のaタグやinputのtype="range"は単に処理を呼び出したり、inputのタイプを指定しているだけなので気にしないでください。

まずv-modelを使ってcurrentTimeを取得しています。なんども言っていますが、v-modelは双方向データバインディングが可能なため、値が変化する度にリロード等の処理をせず、直接表示される値を変化させることが可能です。
そしてv-on:input="seek"はシークバーに触れる(thumbが動く)度に先ほど記述したseek()メソッドが呼び出されます。
最後にv-bind:max="durationTime"はシークの最大値をdurationTimeにしています。そのほか最小値やステップは記述していないためデフォルトの値が使われますので、これも必要に応じて設定してみてください。

現在の再生時間と、全体の再生時間を表示させる(分:秒表示)

v-modelを使ったcurrentTime(現在の再生時間)、v-bindを使ったdurationTime(全体の再生時間)を反映させる処理を見てきた皆さんであれば、おそらくinputに値を反映させたように、文字にも同じように反映させればいいとすぐにわかったと思いますが、今回は少し発展して分:秒(mm:ss)で時間を表示していきたいと思います。

const audio = new Audio

export default {
    data() {
        return {
            currentTime: 0,
            durationTime: 0,
            convertedDurationMin: "00",
            convertedDurationSec: "00",
            convertedCurrentMin: "00",
            convertedCurrentSec: "00"
        }
    },

    mehods:{
        play() {
            audio.src = //オーディオのURLとか

            audio.addEventListener("loadedmetadata", function () {
                const durationMin = Math.floor(audio.duration.toFixed(0) / 60);
                const durationSec = audio.duration.toFixed(0) % 60;

                return {
                    durationTime: audio.duration.toFixed(0),
                    convertedDurationMin: ("00" + durationMin).slice(-2),
                    convertedDurationSec: ("00" + durationSec).slice(-2)
                }
            });
            audio.addEventListener("timeupdate", function () {
                const currentMin = Math.floor(audio.currentTime.toFixed(0) / 60);
                const currentSec = audio.currentTime.toFixed(0) % 60;

                if ((currentMin > this.convertedCurrentMin 
                    && audio.currentTime !== 0)
                    || (currentMin < this.convertedCurrentMin)) {
                    return {
                        currentTime: audio.currentTime.toFixed(0),
                        convertedCurrentMin: ("00" + currentMin).slice(-2),
                        convertedCurrentSec: ("00" + currentSec).slice(-2)
                    }

                } else {
                    return {
                        convertedCurrentSec: ("00" + currentSec).slice(-2)
                    }
                }
            });
            audio.addEventListener("ended", function () {
                return {
                    currentTime: 0,
                    durationTime: 0,
                    convertedDurationMin: "00",
                    convertedDurationSec: "00",
                    convertedCurrentMin: "00",
                    convertedCurrentSec: "00"
                }
            });
            audio.play();
        }
    }
} 

オーディオから取得したdurationTimeを整数に変換し、その値を60で割った数をdurationMin、60で割った数の余りをdurationSecとします。
covertedDurationMinへは"00"にdurationMinを加算した要素から最後の2つを取り出して返し、
covertedDurationSecへは"00"にdurationSecを加算した要素から最後の2つを取り出して返しています。

わかっている人もいると思いますが、"00は"文字列のため、それにdurationMinを加算すると9分以下なら3桁(Ex.009)、10分以上なら4桁(Ex.0010)となってしまいmm表記にはなりませんが、最後の二つの要素のみを取り出せば、9分以下の時は10の位が0になり、10分以上の時はdurationMinと同じ値になるので、mm表記にすることができます。
covertedDurationSecにも同じことが言えるので、これでdurationTimeをmm:ss表記にすることができました。

currentTimeにも同じことが言えますが、currentTimeは値がどんどん変わっていくため、それも考慮してコードを書くと上記のようなコードになります。

currentMinconvertedCurrentMinより大きく、かつaudio.currentTimeが0でない場合というのはcurrentMinが加算されるタイミング(currentSecが0になるタイミングとも言える)の時呼び出されるものです。
thumbを移動させないシークであればこれで問題ありませんが、今回はthumbを移動するため、それに加えてcurrentMinconvertedCurrentMinより大きいときという条件を加えました。こうすることにより1分以上戻った時でも正常に表示できるようになりました。

次に<template>内に記述していきます。

<span v-text="convertedCurrentMin + ':' + convertedCurrentSec"></span>
<span v-text="convertedDurationMin + ':' + convertedDurationSec"></span>

正直そのまますぎて説明することがないので注釈を一つ。ここではspanタグを使っていますが、もちろん別のタグを使っても構いません。
例えばSoundCloudではdurationTimeはaタグになっていて、一度クリックすると残り時間の表示になり、もう一度クリックすると従来通り全体の再生時間を表示することができます。

再生済み用のプログレスバーを作り、元のinputタグに重ねる

まず↓のようなinputと同じサイズのプログレスバーを作ります。
<span class="progress" id="progress"></span>
もちろんタグはdiv等でも構いません。

次にstyleを書いていきます。

span.progress {
    width: /*width*/
    background: linear-gradient(/*YourFavoriteColor*/, /*YourFavoriteColor*/) no-repeat;
    background-size: 0;
    position: absolute;
    pointer-events: none;
}

まずプログレスバーにposition: absoluteを加える等をして、inputの上に重ねます。
background: linear-gradient(/*YourFavoriteColor*/, /*YourFavoriteColor*/) no-repeat;でプログレスバーの色をグラデーションで指定し、backgroud-sizeを使ってプログレスの度合いを表しています。
また最後のpointer-events: none;はプログレスバーの操作を無効化して、その下に配置されているシークバーの操作をできるようにしています。これを指定することにより、プログレスバーが真上に重なっても操作ができるようになりました。

ちなみにプログレスを表示する項目が1つであれば、spanを足さずに直接inputに書くこともできます。
しかしこういったWebサービスではストリーミング再生、つまり再生済みだけでなく読み込み済みのプログレスも作る必要があることが多いため、今回は別のタグにして複数のプログレスを重ねられるようにしました。

次に<script>のtimeUpdate内に記述していきます。

const percent = audio.currentTime.toFixed(0) / audio.duration.toFixed(0) * 100;
document.getElementById("progress").style.backgroundSize = percent + "%";

currentTimeをdurationTimeで割った数に100を掛けた数を定数percentとします。
定数percentの範囲は0 <= percent <= 100なので、background-sizeの値をwidthに対しての百分率とすることができます。そして、span.progressbackground-sizeに定数parcentに"%"を足した値を反映させます。そうするとthumbに従ってプログレスバーが動いているように見えるかと思います。

最後に

長々と書いてきましたが、これで終わりです。初めてな上に眠気と戦いながら書いたので、ミスや分かりづらいところがあったかもしれないですが、少しでも読んでくださった方の参考になれば幸いです。

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