20191211のHTMLに関する記事は10件です。

お店を自由に追加してみよう!CreateView編

今回はCreateView編です。

今までTemplateViewを用いてListView、DetailViewを作成してまいりました。
その1-TemplateViewを使ってみよう!IndexView編
その2-TemplateViewをつかってみよう!Detailview編
お店の一覧、お店の詳細ページを表示ができるようになっている状態の続きと致します。

自分で好きなデータを追加できるって掲示板みたいで楽しいですよね!!

(見慣れない技術の解説)forms.pyでフォームの定義をおこなう

ここであらたなフォームという技術が現れました。
このforms機能はお仕事ではかなり使われることが多いので、慣れておくことを絶対にお勧めしています。
これは何なのかというと、pythonでこのform部分を作ってしまい、モデルと連動してhtmlの<form></form>を作成することになります。
最終的にwebサイトのフォーム部分を表示させることが目的となっていますので、怖がらずで大丈夫ですよ!

編集するファイルはこちら

mysite
│  db.sqlite3
│  manage.py
├─mysite
│  │  settings.py
│  │  urls.py
└─test_app
    │  admin.py
    │  apps.py
    │  models.py
    │  tests.py
    │  urls.py(ここをルーティング設定のために編集)
    │  views.py(ここをCreateView設定のために編集)
    │  forms.py(ここにお店追加の投稿フォームclassを作成)
    ├─migrations
    └─templates
       └─test_app
            └─list.html(ここにお店追加のリンクを表示)
               detail.html
               form.html(お店追加の投稿フォームを表示)

ルーティング設定

このURLでお店の作成ページにリンクできるように設定します。

http://localhost:8000/create

test_appのurls.pyにルーティングを設定します。

urls.py
from django.urls import path
from . import views

app_name = 'test_app'
urlpatterns = [
    path('index/',views.IndexView.as_view(),name='index'),
    path('<int:pk>/',views.DetailView.as_view(),name='detail'),
    path('create/',views.CreateView.as_view(),name='create'),#(ここを追加)
]

解説:app_nameとは、どのアプリ名に対してのルーティングファイルであるか指定する必要があります。ページ上のリンク(htmlで書かれたページのaタグで書かれたリンク)で<a href="{% url 'test_app:create' %}">と記述するため、test_appとアプリ名を設定する必要があります。
また、path('create/',views.CreateView.as_view(),name='create')ではcreate/のURLでviews.pyのCreateViewを呼び出しています。as_view()はテンプレートビューをビューとして扱うため使用されています。このas_view()を付けることによりビュー定義の記述がぐっと楽になります。テンプレートビュー限定のメリットですね。

CreateViewをviews.pyに設定

views.py
from django.views import generic
from .models import Shop
from .forms import ShopCreateForm #ここを追加

# Create your views here.
class IndexView(generic.ListView):
    model = Shop
    template_name = 'test_app/list.html'
class DetailView(generic.DetailView):
    model=Shop
    template_name = 'test_app/detail.html'

class CreateView(generic.CreateView):#ここ以降を追加
    model = Shop
    form_class = ShopCreateForm
    template_name = "test_app/form.html"
    success_url = "/index"

解説:form_classにforms.pyで投稿フォーム用に今回作成するフォームクラスであるShopCreateFormを指定しています。
ちゃんとimport ShopCreateFormを忘れずにお願いします。

views.pyとforms.pyを作成し、行ったり来たりするため、慣れるまで時間がかかりますが頑張りましょう!焦らず無理せず。
きっと慣れてさらに先に進めます!

お店投稿フォームをforms.pyに作成

forms.pyが作成されていない場合、新たに作成する場合があります。作成する場所はtest_appの直下です。views.pyやmodels.pyと同じレベルに作成します。
forms.pyはこのようになります。

forms.py
from django import forms
from .models import Shop

class ShopCreateForm(forms.ModelForm):
    class Meta:
        model = Shop
        fields = ("name","tell_num","address")

解説:forms.ModelFormとは、フォームを作成するためのdjangoの機能となっています。
モデルで定義されているフィールドをそのまま使います。
そのなかで、fieldsにてフォームで表示させるフィールドを選び、絞ることができます。

お店のデータを投稿したい場合、すでにShopのフィールドは作成されています。実際にmodels.pyの内容はこちらで、nametell_numaddresscreated_atなどフィールドが作成されています。

models.py
from django.db import models

# Create your models here.
class Shop(models.Model):
    #各フィールドの定義
    name = models.CharField('shopname',max_length=30)
    tell_num = models.CharField('tell_number',max_length=13)
    address = models.CharField('address',max_length=30)
    created_at = models.DateTimeField(auto_now_add=True)

    #admin画面の表示内容
    def __str__(self):
        return self.name

このShopクラスのフィールドをそのままforms.pyで使うことを意味しているのです。
ModelFormを用いると大変楽にフォームページを作成できるのです!

投稿ページのform.htmlを作成

mysite/test_app/templates/test_app/form.html
<!DOCTYPE>
<html>
    <head>
    </head>
    <body>
    <p>お店の作成</p>
        <form method="post">
            {% csrf_token %}
            {{ form.as_p }}
            <button type="submit">save</button>
        </form>
    </body>
</html>

解説:<form method="post">でフォームタグを作成しています。
{% csrf_token %}はフォームデータに改ざん防止の特殊な何かのデータを添えて送信するもので、必須です。
これを入れないと、djangoがエラーとなるため、必ず入れましょう。
{{ form.as_p }}はforms.pyで作成したShopCreateFormをviews.pyのform_classで指定していたため、html側ではformと記述するだけでフォームが呼び出せます。formと書く、と刷り込ませて良いです!
<button type="submit">save</button>ではデータ送信ボタンを作成しています。」

「お店の投稿」リンクを一覧ページに作成

test_app/templates/test_app/list.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
  </head>
  <body>
  <p>一覧の表示</p>
  <p><a href="{% url 'test_app:create' %}">お店の追加</a></p><!-- この行を追加 -->
  <table>
    <tr>
    </tr>
    {% for shop in shop_list %}
    <tr>
      <td>{{ shop.name }}</td>
      <td><a href="{% url 'test_app:detail' shop.pk %}">詳細</a></td>
    </tr>
    {% endfor %}
  </table>
  </body>
</html>

解説:お店の追加ページへリンクするためにリンクを書いています。パスはtest_appというアプリ名のcreateを指定しています。

formの表示の確認を行う

「お店の追加フォーム画面」で団子屋という名前のお店を追加してみます。
create画面.png

「リスト画面」で追加されたデータを確認してみましょう。
クリエイト後トップ画面.png

「団子屋詳細画面」で団子屋の詳細を確認してみましょう。
団子屋詳細ページ.png

お疲れさまでした✨

最後に

データ追加のための設定は必ずと言っていいほど重要なdjangoスキルとなるでしょう。CreateViewを用いてスピーディに作成ができることでかなりDjangoに慣れているといえると思います。
3つくらい自分でアプリを作成してみれば、データの追加、詳細、一覧が含まれるような、お店掲示板、日記などのアプリケーションが作成できるようになっていると思います。

わからないところや質問など受け付けておりますので、一緒に頑張ってゆきましょう!

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

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

100日チャレンジの181日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

181日目は

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

HTML・CSSでよく使う記述

初めに

よく使う記述で、毎度調べたりするのが面倒なので、ここに書き溜めていきます。

HTML編

HTML空の記述

<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title></title>
</head>
<body>

</body>
</html>

CSSの読み込み

<!-- cssの読み込み -->
<link rel="stylesheet" href="./css/mobile.css">

<!-- メディアクエリーで条件付きのcssの読み込み -->
<link rel="stylesheet" href="./css/xxx.css" media="screen and (min-width: 640px)">

CSS編

メディアクエリ

@media screen and (min-width: 640px) {
  /* 横幅640pxより大きくなると適応 */
}

親要素をはみ出す

.body {
  width: 640px;
  margin: 0 auto;
}
.title {
  margin-left: calc(((100vw - 100%) / 2) * -1);
  margin-right: calc(((100vw - 100%) / 2) * -1);
  background: #ccc;
}
.title span {
  width: 640px;
}

↓↓こういうやつ↓↓
download.png
対応ブラウザ https://caniuse.com/#search=calc
対応ブラウザ https://caniuse.com/#feat=viewport-units

以上

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

Bootstrap 4 のGRID SYSTEMを使ってWebサイトのコラムをレスポンシブ化する

BootStrapでコラムをレスポンシブデザインにする

HTML, CSSだけだとレスポンシブ化って難しいけど、Bootstrapを使用すると簡単!

まず【前提】WEBサイトの横幅は12個のBOXでできている

←------------------WEBサイトの横幅-----------------→

1 2 3 4 5 6 7 8 9 10 11 12

BootstrapのGrid SystemではWidthが12個のBOXで敷き詰められている。

PC,タブレット, スマホによって、その12個のBOXのうちの何個を使用するかをそれぞれ指定できる。説明難しいからとりあえずコード。

column-responsive.html
<div class="container">
  <div class="row">
    <div class="col-lg-2 col-md-3 col-sm-12" style="background-color:red; border: 1px solid;">
        コンテンツ
    </div>
  </div>
</div>

まずdiv class="row(行)"の中にcolumn(列) divを作成する。

ここでポイントが
①col-lg-2 (PC表示の時は12個のBOXのうち2個のスペース使いますよ)
②col-md-3 (タブレット表示の時は12個のBOXのうち3個のスペース使いますよ)
③col-sm-12 (スマホ表示の時は12個のBOXのうち12個のスペース使いますよ)

つまり
①2/12 = 6分割(6コラム)
②3/12 = 4分割(4コラム)
③12/12 = 1分割(1コラム)
となる。

ちなみにlgはPC、mdはタブレット、smはスマホの表示コラムってしたけど、厳密には横幅のPixcel数で区切っているみたい。

スクリーンショット 2019-12-11 17.50.47.png
(BootStrapのHPより抜粋)

レスポンシブ化、Bootstrapを使うとめちゃくちゃ簡単だからとてもおすすめ。
ちなみにコラムのレスポンシブ化するときは、基本的に最初にclass="container"のdivを使うから気をつけてね。

ちなみにこちらが公式ドキュメント
https://getbootstrap.com/docs/4.4/layout/grid/

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

電車の発車案内板をHTMLとCSSだけで作ってみる~試行錯誤編その2~

この記事は
電車の発車案内板をHTMLとCSSだけで作ってみる~試行錯誤編その2~
の継続記事です。

前回の反省点

・ドットの精度が低かった
・もう少しドットだけでフォントを生成する手法を勉強したほうがいい

ということでした。

ドットの研究

dot.jpg

Photoshopで、700%まで拡大し、見てみると、画像のふちに原色より薄い領域があることに気が付きました。

やってみる

今回は「品」だけで。

CSS(Scss)

style2.scss

 $pixel:2px;
 $pixel2:2px; 
.guide{
  width:400px;
  height: 50px;
  background:#000;

  &-inner{
    width:280px;
    height: 40px;
    display:flex;
  } 
  &-text-char1{
    width:40px;
    height: 40px;
   display:grid;
   grid-template-columns:1fr repeat(16,$pixel) 1fr;
   grid-template-rows:repeat(25,$pixel2);
   grid-template-areas:
      "... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ..."
      "... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ..."
      "... ... ... w01 g01 g01 g01 g01 g01 g01 g01 g01 g01 w02 w02 ... ... ..."
      "... ... ... w03 g02 g02 w04 w04 w04 w04 w04 g03 g03 w05 w05 ... ... ..."
      "... ... ... w06 g04 g04 w07 ... ... ... ... w08 g05 g05 w09 ... ... ..."
      "... ... ... w10 g06 g06 w11 ... ... ... ... w12 g07 g07 w13 ... ... ..."
      "... ... ... w14 g08 g08 w15 ... ... ... ... w16 g09 g09 w17 ... ... ..."
      "... ... ... w18 g10 g10 w19 ... ... ... ... w20 g11 g11 w21 ... ... ..."
      "... ... ... w22 g12 g12 w24 ... ... ... ... w25 g13 g13 w26 ... ... ..."
      "... ... ... w27 g14 g14 g14 g14 g14 g14 g14 g14 g14 g14 w28 ... ... ..."
      "... ... ... w29 g15 g15 g15 g15 g15 g15 g15 g15 g15 g15 w30 ... ... ..."
      "... ... ... ... w31 w31 w31 w31 w31 w31 w31 w31 w31 w31 ... ... ... ..."
      "... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ..."
      "... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ..."
      "... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ..."  
      "... ... w32 g16 g16 g16 g16 ... ... ... w33 g17 g17 g17 g17 w34 ... ..."
      "... ... w35 g18 w36 w36 g19 ... ... ... w37 g20 w38 w38 g21 w39 ... ..."
      "... ... w40 g22 ... ... g23 ... ... ... w41 g24 ... ... g25 w42 ... ..."
      "... ... w43 g26 ... ... g27 ... ... ... w44 g28 ... ... g29 w45 ... ..."
      "... ... w46 g30 ... ... g31 ... ... ... w47 g32 ... ... g33 w48 ... ..."
      "... ... w49 g34 ... ... g35 ... ... ... w50 g36 ... ... g37 w51 ... ..."
      "... ... w52 g38 g38 g38 g38 ... ... ... w53 g39 g39 g39 g39 w54 ... ..."
      "... ... w55 g40 g40 g40 g40 ... ... ... w56 g41 g41 g41 g41 w57 ... ..."
      "... ... w58 g42 ... ... g43 ... ... ... w59 g44 ... ... g45 w60 ... ..."
      ;
}

  @for $i from 1 through 67 { 
  .char1-guide__dotg#{$i}{ 
    @if $i < 10 { 
      grid-area:g0#{$i}; 
      } @else { 
      grid-area:g#{$i}; 
    } 
     background-color:#08eb0e; 
   }

  .char1-guide__dotw#{$i}{ 
    @if $i < 10 { 
      grid-area:w0#{$i}; 
      } @else { 
      grid-area:w#{$i}; 
    } 
     background-color:#d8fad8; 
   }
  }
}

薄い領域をw~にし、2色構成で、作ってみました。(並び作るの大変でした・・)

HTML(ejs)

dotsample.ejs
<html>
    <head>
        <link rel="stylesheet" href="./css/style2.css"> 
    </head>
    <body>

        <div class="guide">
            <div class="guide-inner">
                <div class="guide-text-char1">
                    <% pix1 = 1; %>
                    <% pix2 = 1; %>
                     <% for(i=0; i<=45; i++){ %>
                     <% for(j=1; j<=25; j++){ %>
                          <div class="char1-guide__dotg<%= pix1 %>"></div>
                       <% } pix1++; }  %>
                      <% for(k=0; k<=60; k++){ %>
                       <% for(l=1; l<=25; l++){ %>
                          <div class="char1-guide__dotw<%= pix2 %>"></div>
                       <% } pix2++; }  %>
                </div>
            </div>
        </div>
    </body>
</html>


2種類あるので、変数やfor文もその数増えます。

※サーバーに負荷がかかりそうなので一旦削除しました。別な方法考えます。

やっぱり、精度が低いです・・

反省点

・ドットの文字の原理をもう少し勉強したほうがいい
・制度を上げる訓練をした方がいい

このあと

しばらく1週間置いて研究し続けてみたいと思います。

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

画像をドラッグ&ドロップで登録してプレビュー表示

備忘録

input:fileの画像登録時にドラッグ&ドッロップでinputに値を渡し、プレビューを出す記述。
(通常登録も対応)

JSライブラリ依存せずに使用(してるはず)。

CODEPEN

See the Pen 画像をドラッグ&ドロップで登録してプレビュー表示 by manabu tanaka (@tonkatsu) on CodePen.

記述

html ドラッグ&ドロップするエリア
<form method="post" enctype="multipart/form-data">
    <div id="dragDropArea">
        <div class="drag-drop-inside">
            <p class="drag-drop-info">ここにファイルをドロップ</p>
            <p>または</p>
            <p class="drag-drop-buttons">
                <input id="fileInput" type="file" accept="image/*" value="ファイルを選択" name="photo" onChange="photoPreview(event)">
            </p>
            <div id="previewArea"></div>
        </div>
    </div>
    <button type="submit" name="submit" value="登録">登録<button>
</form>
css 簡単に整形
#dragDropArea{
  background-color: #f4f4f4;
  margin: 10px;
  padding: 10px;
  border: #ddd dashed 5px;
  min-height: 200px;
  text-align: center;
}
#dragDropArea p{
    color: #999;
    font-weight: bold;
    font-size: 14px;
    font-size: 1.4em;
}
#dragDropArea .drag-drop-buttons{
    margin-top: 20px;
    font-size: 12px;
    font-size: 1.2em;
}
.drag-drop-buttons input{
    margin: auto;
}

JS ドラドロイベントでごにょごにょ&選択時にごにょごにょ
var fileArea = document.getElementById('dragDropArea');
var fileInput = document.getElementById('fileInput');
fileArea.addEventListener('dragover', function(evt){
  evt.preventDefault();
  fileArea.classList.add('dragover');
});
fileArea.addEventListener('dragleave', function(evt){
    evt.preventDefault();
    fileArea.classList.remove('dragover');
});
fileArea.addEventListener('drop', function(evt){
    evt.preventDefault();
    fileArea.classList.remove('dragenter');
    var files = evt.dataTransfer.files;
    console.log("DRAG & DROP");
    console.table(files);
    fileInput.files = files;
    photoPreview('onChenge',files[0]);
});
function photoPreview(event, f = null) {
  var file = f;
  if(file === null){
      file = event.target.files[0];
  }
  var reader = new FileReader();
  var preview = document.getElementById("previewArea");
  var previewImage = document.getElementById("previewImage");

  if(previewImage != null) {
    preview.removeChild(previewImage);
  }
  reader.onload = function(event) {
    var img = document.createElement("img");
    img.setAttribute("src", reader.result);
    img.setAttribute("id", "previewImage");
    preview.appendChild(img);
  };

  reader.readAsDataURL(file);
}

参考サイト

https://www.kabanoki.net/1552/
http://koheik.hatenablog.com/entry/2016/07/08/152936
https://qiita.com/sanapon1020/items/77d37fe1fd6f87740e1b

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

レスポンシブルサイト作成の手順と注意点

はじめに

ここ最近にPCとモバイルのどちらにも対応できるレスポンシブルサイトについて学んだので、それについてここで復習がてらにアウトプットしようと思います。

レスポンシブルサイトについて

レスポンシブルサイトとは、上で軽く触れた様にPC対応とモバイル対応の両方ができるサイトです。
具体的に言うと、メディアクエリを使って各端末ごとのCSSを記載していき、CSSを切り替えることで様々な端末絵の対応が可能になります。
しかし、レスポンシブルサイトにはメリットもありデメリットもあります。それを軽くまとめます。

メリット
PC対応とモバイル対応が両方できるため、サイトが一つだけですみ管理が簡単。

デメリット
HTML構造を同じにしないといけないため、レイアウトに制限あり。
必要な技術力が専用サイトよりも高い。

作成の流れ

1、スマホ版のレイアウトとPC版レイアウトのデザイン案を作成する。
この際に、レイアウトを先に考えるのではなく、必要コンテンツを先に出して、それを元にレイアウトを考える。

2、デザインにセクションやHTML要素を割り当てていきHTML構造を作成する。

3、各要素にクラス名などのセレクタ名をつけていく。
この際、セレクタ名は複数開発に仕様が出ない様に一目でわかるものにする。

4、CSSを割り当てていく。

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

2019年 スマホブラウザ対応で苦戦したこと

私は普段業務で、Webページの保守・運用を主にしております。
特にスマホブラウザメインのサイトを扱っているため、スマホでの表示崩れや仕様に対応しなければならないことが多いです。

そのなかでも、今年1年の間で直すのにてこずったスマートフォン向けの対応について、今回は備忘録もかねて紹介してみようと思います。

1. iOS編

1-1. 横画面表示に切り替えると、文字の大きさがバラバラになる

文字サイズがバラバラになってしまったコード

まずは、実際に横画面にして崩れてしまっていた箇所を、最小限のコード量で再現してみます。

<p class="line-height-big">てすと</p>
<p class="line-height-big">てすてす<span class="red">てすと</span></p>
<style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>
  • まずすべての要素(*セレクタ)に line-height:1を指定。
  • 異なる値のline-heightを指定したクラス(今回は.line-height-big)を作成。
  • pタグを2つ用意し、片方に.line-height-bigを指定
  • .line-height-bigで囲った要素の子要素にただのテキストとspanで囲ったテキストを配置

スクリーンショット 2019-12-09 11.47.07.png
スクリーンショット 2019-12-09 13.41.58.png

横画面表示にすると、なぜか.line-height-bigの中のspanの中の文字だけ小さくなってしまいました。
ちなみにclass="red" はみやすくするためにつけたので、文字を赤くしなくても同じことが起こります。

原因

ブラウザを横画面にした時に、文字サイズを調整する機能がうまく動作せずにサイズがバラバラになってしまいます。
下記のコードのように-webkit-text-size-adjust: 100%; を指定すれば、横画面にしても文字サイズが変わらず、大きさがバラバラになることもありません。

body {
  -webkit-text-size-adjust: 100%;
}

スクリーンショット 2019-12-09 13.16.09.png
スクリーンショット 2019-12-09 13.16.26.png

だけど、横画面にした時、文字が大きくなってほしい

しかし今回は、横画面にした時に文字サイズが大きくなって欲しかったため、-webkit-text-size-adjust: 100%;は使わずに対応するために挙動について検証してみました。

 パターン1
<p class="line-height-big">てすと</p>
<p class="line-height-big">てすてす<span class="red">てすと</span></p>
<style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>

スクリーンショット 2019-12-09 13.55.20.png
line-heightの値が異なる要素だけ小さくなってしまっているようでした。

 パターン2
<p>てすと</p>
<p class="line-height-big">てすてす<span class="red">てすと</span></p>
<style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>

スクリーンショット 2019-12-09 13.46.06.png
この場合も同様、文字が小さくなってしまっている箇所はline-heightの値が他と異なっています。

解決方法

ということで、line-heightの値が一定になるように修正します。

 <p class="line-height-big">てすと</p>
 <p class="line-height-big">てすてす<span class="red line-height-big">てすと</span></p>
 <style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>

上記のコードのようにline-heightの値を揃えれば、文字の大きさが一定になりました。

スクリーンショット 2019-12-09 11.58.54.png

でも、下記のようにpタグが1つだけの場合だと

<p class="line-height-big">てすてす<span class="red">てすと</span></p>
<style>
 *{
   line-height: 1;
 }

 .line-height-big {
   line-height: 1.2;
 }

 .red {
   color: #ff0000;
 }
 </style>

スクリーンショット 2019-12-09 14.44.39.png

line-height の値が異なるものが混じっていますが、文字サイズはバラバラになりません。

line-heightの値が異なる要素が3つ以上ある場合、バラバラになってしまう?ように思えますが
どの文字が小さくなってしまうのかなどは、規則性がわからずじまいでした、、、

しかし今回のように、同じブロックの中に、さまざまなline-heightが混在しないようにすれば、他の原因で文字サイズがバラバラになってしまう事象には遭遇していません。

詳しい仕様などがわかる方がもしいらっしゃれば、コメントでぜひ教えていただけると助かります?

1-2. 入力フォームにカーソルを合わせたときにズームしないでほしい

iOS端末では、input要素のフォントサイズが16px以下だと、入力フォームびカーソルを合わせたときに拡大表示される機能があります。

textarea {
  font-size: 10px;
  width: 60%;
  height: 50px;
  margin: 0 20%;
  padding: 10px;
  resize: none;
}

font-sizeを16px以上にすれば拡大されないようになります。

textarea {
  font-size: 16px;
  width: 60%;
  height: 50px;
  margin: 0 20%;
  padding: 10px;
  resize: none;
}

font-size 16px以下で、拡大しないように実装したい場合は、scaleを利用します。

textarea {
  /* scale(0.5)で半分の大きさになってしまうので、全て2倍の値にする */
  font-size: 20px;

  width: 120%;
  height: 100px;
  margin: 0 40%;
  padding: 20px;

  resize: none;
  transform: scale(.5);
  transform-origin: left top;
}

scale によって文字以外も縮小されてしまい、見た目が少し変わってしまうので、縮小率に合わせて大きい値を指定するか、入力フォームをdiv などで括って、そこにcssを当てるなどで対応できると思います。

こちらの方法使用する場合は、標準の機能を動作させないようにすることになるため、フォントサイズが小さくても操作性に問題がないか、要検証です?

2. Android編

2-1. Android4以下の一部ブラウザでFlexが崩れる

これは単純にブラウザが対応していないだけでした?
ベンダープレフィックス付与すれば、Android4以下でもFlexを使用できます。

Flexコンテナ

.flex {
  display: -webkit-box; /* Android用 */
  display: flex;
}

Flexカラム

.flx-column{
    -webkit-box-flex: 1; /* Android用 */
    flex: 1 1 0;
}

justify-contentプロパティ

.flex-start{
    -webkit-box-pack: start; /* Android用 */
    justify-content: flex-start;
}

.flex-end{
    -webkit-box-pack: end; /* Android用 */
    justify-content: flex-end;
}

.flex-center{
    -webkit-box-pack: center; /* Android用 */
    justify-content: center;
}

.flex-space-between{
    -webkit-box-pack: justify; /* Android用 */
    justify-content: space-between;
}

align-itemsプロパティ

.flex-start{
    -webkit-box-align: start; /* Android用 */
    align-items: flex-start;
}

.flex-end{
    -webkit-box-align: end; /* Android用 */
    align-items: flex-end;
}

.flex-center{
    -webkit-box-align: center; /* Android用 */
    align-items: flex-center;
}

.flex-baseline{
    -webkit-box-align: baseline; /* Android用 */
    align-items: baseline;
}

.flex-stretch{
    -webkit-box-align: stretch; /* Android用 */
    align-items: stretch;
}

align-content は使えません、、、?

制作のときは、開発者ツールを使ってAndroid用のベンダープレフィックスが付いているcssのみを有効にして表示確認をすれば、Flexが未対応の実機でも崩れず表示できました。

まとめ

以上、対応に手こずったスマホブラウザ対応についてまとめてみました。
同様の現象で困っている人のヒントになれば幸いです。。。?‍♂️

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

CSSでパタパタ動くランキングボードを作った

はじめに

12月になると流行語大賞をはじめとする、様々な〇〇大賞が発表されます。
今回は、そんなときに使われるランキングボードをCSSで作りました。

CSSで作ったらこうなった

オレンジの「PUSH」ボタンを押すとランキングがパタパタと動き出します。
今年の流行語大賞をランキングボードに出してみます。
(※ スマホでは上手く表示されないかもしれません。。)

See the Pen CSS Ranking Board by saka212 (@saka212) on CodePen.

ソース

カスタマイズに必要な部分のHTMLとCSSを載せます。
全体はちょっと長いのでcodepenで。
https://codepen.io/saka212/pen/PowZppx

ランキングが動き出す仕組み

css
input[type="checkbox"] {
  display: none;
}

label {
  display: inline-block;
  box-sizing: border-box;
  width: 80px;
  height: 50px;
  margin-right: 5px;
  line-height: 50px;
  background: #ffa500;
  border: solid 1px #ffa500;
  border-radius: 4px;
  border-bottom: 4px solid #d37800;
  text-shadow: 1px 1px 1px rgba(0,0,0,0.2);
  color: #fff;
  text-align: center;
  font-weight: bold;
  vertical-align: top;
  cursor: pointer;
}


.btn:checked + label + .frame .flip:nth-of-type(1) {
  /* animation: keyframe名 周期 開始タイミング 回数 アニメショーン終了後のスタイル指定 */
  animation: frame-rotate var(--duration) calc(var(--delay) * 0) var(--count) forwards;
}
.btn:checked + label + .frame .flip:nth-of-type(2) {
  animation: frame-rotate var(--duration) calc(var(--delay) * 1) var(--count) forwards;
}
.btn:checked + label + .frame .flip:nth-of-type(3) {
  animation: frame-rotate var(--duration) calc(var(--delay) * 2) var(--count) forwards;
}
.btn:checked + label + .frame .flip:last-child {
  display: none;
}

チェックボックスを隠し、ボタン化したラベルを押すことで、ランキングがパタパタと動きます。
動きの流れを簡単に説明すると...

1.チェックボックスとラベルタグを関連付ける。
  ↓
2.関連付けることで、ボタン化したラベルをクリックするとチェックが入る。
  ↓
3.チェックされたときに適用されるCSSに、animationプロパティを書いておくことでアニメが動く。

表示したいパタパタの数の合わせて、
.btn:checked + label + .frame .flip:nth-of-type(1) {...}
の部分は増やしておきます。animationプロパティの値は、CSSカスタムプロパティで設定すると便利です。

ランキング内容を変えて遊びたいとき

html
<div class="row">
  <input type="radio" id="btn1" class="btn">
  <label for="btn1">PUSH ME</label>
  <div class="frame">
    <div class="flip" data-txt="ONE TEAM" data-txt-next="令和"></div>
    <div class="flip" data-txt="令和" data-txt-next="タピる"></div>
    <!-- ↓↓ この 「data-txt-next」にパタパタが止まった止まったときに表示したいテキスト -->
    <div class="flip" data-txt="タピる" data-txt-next="ONE TEAM"></div>
    <!-- ↓↓ この「data-txt」にボタンを押す前に表示するテキスト -->
    <div class="flip open" data-txt="大賞"></div>
  </div>
</div>

ランキングひとつ分のhtmlです。
3行のランキングを表示しているので、このhtml部分を3つ用意しています。
ボタンを押す前に表示するテキストを、
<div class="flip open" data-txt="..."></div>data-txt="..."
に書きます。
パタパタが止まったときに表示したいテキストは、そのひとつ上のdivのdata-txt-next="..."に書きます。

感想

rotateを使ったアニメーションはパズルですね。
よくよく整理しながら進めていかないと、何を作っているかわからなくなります。
リアリティーを出せるように、いろいろなやり方をためしているうちに、自分の頭の中もパタパタしてきたので「それっぽさ」が出る方向に転換しました。
もっとシンプルな作り方もあるかもしれません。

おわりに

「2019年ティーンが選ぶトレンドランキング」は、ほとんどわかりませんでした...。

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

立方体を描画してみよう!CSSだけで3D表現【フロントエンド】

はじめに

今回は,WebGL等を使わないで,単純な3DオブジェクトをCSSだけで描画する方法についてご紹介しようと思います.

CSSでの3D表現の特徴

確かに複雑なオブジェクトを作るのであれば,WebGLを使うのが好ましいでしょう.
しかし,CSSでやる良さもあるので,主なメリットとデメリットを以下に記述します.

  • CSSで3Dをやるメリット

    • 直感的に作れる.
    • イベントなどを設定しやすい.
    • 見た目をCSSで簡単に変更できる.
  • CSSで3Dをやるデメリット

    • 複雑な立体は作るのが大変.
    • 曲線のある立体は作るのが難しい.
    • 複雑なものを作ると時間が溶ける.

立方体のサンプル

See the Pen 3D Box by AO2324 (@AO2324) on CodePen.

円柱のサンプル

See the Pen 3D Cylinder by AO2324 (@AO2324) on CodePen.

クリックイベントをつけた立体のサンプル

See the Pen 3D Box has event by AO2324 (@AO2324) on CodePen.

使用するCSSプロパティ

  • transform-style
  • transform
  • perspective

transform-style (描画形式)

子要素の変形を立体的に描画するか平面的に描画するかを指定します.

平面的(初期設定)
transform-style:flat;
立体的
transform-style:preserve-3d;

See the Pen 3D Box (Flat / 3d ) by AO2324 (@AO2324) on CodePen.

transform (要素の移動や回転)

transformプロパティを使用することで,要素を平行移動や回転,拡大など,変形させることができます.

指定方法は,transformの後にどう変形させるかを続けて記述します.
transform: 変形1 変形2;
変形の書き方
変形の種類+基本とする軸(値)

  • 変形の種類
    • translate : 平行移動
    • rotate : 回転
    • scale : 大きさ
    • skew : 傾斜
  • 基本とする軸
    • X : x軸
    • Y : y軸
    • Z : z軸
    • なし : ()の中にx軸とy軸をカンマ(,)で区切って表記
    • 3d : ()の中にx軸とy軸とz軸をカンマ(,)で区切って表記
サンプル
transform: translateX(50px) translateY(100px) rotateZ(90deg);
/* x軸方向に50px,y軸方向に100px平行移動したのち,z軸を中心に90度回転 */
transform: translate(50vw, 50vh);
/* x軸方向に50vw,y軸方向に50vh平行移動 */

perspective (遠近感)

3Dのオブジェクトに遠近感をもたせます.
数値が小さいほど魚眼レンズのようになり,大きければ大きいほど全ての幅が均等になります.
スクリーンショット 2019-12-10 23.35.30.png
perspective:200px;
スクリーンショット 2019-12-10 23.20.10.png
perspective:10000px;
数値が小さい(200px)と上のような見え方に,数値が大きい(10000px)と下のような見え方になります.
個人的には 800px ~ 1000px くらいがちょうどいい気がします.
スクリーンショット 2019-12-10 23.20.28.png
perspective:1000px;

実際に立方体を作ってみよう!

Step1

まず,HTMLで立体の面となる要素を定義してあげます.

html
<div id="scene">
  <div class="boxBase">
    <div class="top"></div>
    <div class="bottom"></div>
    <div class="front"></div>
    <div class="back"></div>
    <div class="left"></div>
    <div class="right"></div>
  </div>
</div>

ここで,sceneは3Dオブジェクトを表示する場所,boxBaseは立方体,その中の要素は立方体のそれぞれの面を表しています.
これをCSSのtransformを使って変形することで,ペーパークラフトのように立体を作ることができます.

Step2

何も指定しないと平面的に描画してしまうので,transform-style:preserve-3d;をboxBaseに設定して,子要素を立体的に表示するようにしてあげましょう.
ここで,一辺の長さも決めてしまいましょう.

css(1/4)
.boxBase {
  transform-style:preserve-3d;
  width:200px;
  height:200px;
}

Step3

立方体の面となる要素の設定を行い,ついでに色や縁にもスタイルを適応させましょう.

css(2/4)
.boxBase > div {
  position:absolute;
  width:100%;
  height:100%;
  background-color:rgba(100, 100, 100, 0.7); /* 面の色 */
  border:0.5px solid black; /* 縁 */
}

Step4

それぞれの面を変形して,立方体を組み立てていきましょう.

css(3/4)
.boxBase > .top {
  transform:translateY(100px) rotateX(-90deg);
}
.boxBase > .bottom {
  transform:translateY(-100px) rotateX(90deg);
}
.boxBase > .front {
  transform:translateZ(100px);
}
.boxBase > .back {
  transform:translateZ(-100px) rotateX(180deg);
}
.boxBase > .left {
  transform:translateX(-100px) rotateY(-90deg);
}
.boxBase > .right {
  transform:translateX(100px) rotateY(90deg);
}

Step5

perspectiveで遠近感を調整しましょう.

css(4/4)
#scene {
  perspective: 1000px;
}

立方体の完成

立方体(htmlファイル)
<div id="scene">
  <div class="boxBase">
    <div class="top"></div>
    <div class="bottom"></div>
    <div class="front"></div>
    <div class="back"></div>
    <div class="left"></div>
    <div class="right"></div>
  </div>
</div>

<style>
#scene {
  perspective: 1000px;
}
.boxBase {
  transform-style:preserve-3d;
  width:200px;
  height:200px;
}
.boxBase > div {
  position:absolute;
  background-color:rgba(100, 100, 100, 0.7);
  border:0.5px solid black;
  width:100%;
  height:100%;
}
.boxBase > .top {
  transform:translateY(100px) rotateX(-90deg);
}
.boxBase > .bottom {
  transform:translateY(-100px) rotateX(90deg);
}
.boxBase > .front {
  transform:translateZ(100px);
}
.boxBase > .back {
  transform:translateZ(-100px) rotateX(180deg);
}
.boxBase > .left {
  transform:translateX(-100px) rotateY(-90deg);
}
.boxBase > .right {
  transform:translateX(100px) rotateY(90deg);
}
</style>

アニメーションをつけてあげると立体になっている事がよくわかるので,ぜひ試してみてください.

立方体のアニメーション
#scene {
  perspective: 1000px;
  width:200px;
  height:200px;
  position:relative;
  top:50vh;
  left:50vw;
  transform:translateX(-50%) translateY(-50%);
}
.boxBase {
  transform-style:preserve-3d;
  width:200px;
  height:200px;
  animation: turnAround 30s linear 0s infinite normal none running;
}
@keyframes turnAround {
  0%{
    transform:rotateX(0deg) rotateY(0deg);
  }
  100%{
    transform:rotateX(360deg) rotateY(360deg);
  }
}

See the Pen 3D Box by AO2324 (@AO2324) on CodePen.

最後に

今回はCSSでの3D表現のざっくりとした説明と,簡単な立体の作り方を書かせていただきました.
これだけだと,実際のWebページやアプリ開発でどのように活かせるかわからないかもしれません.
ですが,発想次第ではいろいろな事ができるので,ぜひCSSでもっともっと遊んでみてください.
スクリーンショット 2019-12-11 1.34.08.png
↑人型の立体物 ↓Webサイトのナビゲーション
スクリーンショット 2019-12-11 1.32.15.png

参考

CSS3D!まるでWebGLのような3Dを超気軽に実装するCSS技 (中矢 雄介/Creator)

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