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

即時に更新されるチャット機能(Action Cableの実装)

即時に更新されるチャットアプリ

  • Action Cableを用いた、リアルタイムチャットアプリを作成する

まとめてコードずらりします⬇︎

ターミナル
% cd projects
% rails _6.0.0_ new mini_talk_app -d mysql
% cd mini_talk_app
% rails db:create
ターミナル
% rails g controller messages new
% rails g model message text:text
% rails db:migrate
app/config/routes.rb
Rails.application.routes.draw do
  root 'messages#new'
  resources :messages, only: [:create]
end
app/controllers/messages_controller.rb
class MessagesController < ApplicationController
  def new
    @messages = Message.all
    @message = Message.new
  end

  def create
    @message = Message.new(text: params[:message][:text])
  end
end
app/views/messages/new.html.erb
<h3>mini_talk_app</h3>
<%= form_with model: @message do |f| %>
  <%= f.text_field :text %>
  <%= f.submit '送信' %>
<% end %>
<div id='messages'>
  <% @messages.reverse_each do |message| %>
    <p><%= message.text %></p>
  <% end %>
</div>

この時点で下記のようになっているはず

d6806db02ad04b485928bbd124c73f1a.png

Action Cableの実装(先ほどの続き)

ターミナル
% rails g channel message
app/channel/message_channel.rb
class MessageChannel < ApplicationCable::Channel
  def subscribed
    stream_from "message_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end
app/controller/messages_controller.rb
class MessagesController < ApplicationController
  def new
    @messages = Message.all
    @message = Message.new
  end

  def create
    @message = Message.new(text: params[:message][:text])
    if @message.save
      ActionCable.server.broadcast 'message_channel', content: @message
    end
  end
end
app/javascript/channels/message_channel.js
import consumer from "./consumer"

consumer.subscriptions.create("MessageChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {
    const html = `<p>${data.content.text}</p>`;
    const messages = document.getElementById('messages');
    const newMessage = document.getElementById('message_text');
    messages.insertAdjacentHTML('afterbegin', html);
    newMessage.value='';
  }
});

現場からは以上です!

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

【初心者でもわかる】imgの画像がぼやける理由と対策

どうも7noteです。なんだか画像がぼやけてるような気がする時の対処法

imgタグの画像は画像データと全く同じpxに指定するのが基本!

画像データが大きいが、無理に150pxの幅の箇所に画像を使用してしまうとぼやけてしまいます。(おそらくChromeのみ)

画像がぼやけないためには

①使う予定の場所のpxに合わせて画像をトリミング

一番正攻法です。
ただ、レスポンシブに対応しなければならない場面もあると思うので、実際にはPCでの指定よりも大きなサイズの画像が必要になうrことが多いです。

style.css
img {
  width: 100px;  /* 画像データの横幅も100px */
}

②画像データを使う場所の2倍の大きさで書き出す。

imgの特徴として、元データの半分のサイズで使う場合などは比較的綺麗み見えます。

レスポンシブサイトを作るときは、スマートフォンの画像サイズに合わせて画像を書き出す必要があります。
スマホは倍の画角の画像が必要になるため、横幅350pxのスマホに幅いっぱい画像を表示する場合最低でも700pxの画像が必要になります。
しかし、パソコンでは幅を400pxの場所に画像を使う場合、画像は700pxに対して使う場所は400pxと綺麗に割りきれません。

そこで、画像サイズを800pxで予め書き出しておくことで、PC表示でもスマホでも綺麗に見せることができます。

③画像をPC用とスマホ用2種類に分ける

多くの場合、レスポンシブサイトのため少しでも軽くする意図で1枚の画像でやろうとしますが、画像の綺麗さを優先するのであればPCもスマホも別の画像として登録しておいて呼び出す方が良い出しょう。

index.html
<img src="./images/img_pc.jpg" class="pc_img">  /* pc用の画像 */
<img src="./images/img_sp.jpg" class="sp_img">  /* スマホ用の画像 */
style.css
.pc_img {
  display: inline;
}
.sp_img {
  display: none;
}

@media screen and (max-width: 700px) {
  .pc_img {
    display: none;
  }
  .sp_img {
    display: inline;
  }
}

※クラスを使わずに、pcとスマホの画像を自動で切り換える方法もあるので、今度記事にします。

④CSSで解決

img {
  -webkit-backface-visibility: hidden;
}

これが一番簡単かも。

参考元:https://creativememomemo.com/chrome_image_blur/

まとめ

CSSで一応解決できるので、いろいろ紹介したけど結局④の方法が一番良いかも。
③のpcとスマホで画像を切り換える方法は全く違う画像に切り換える方法としても使えるのでむしろそっちの使い方の方が主流かも。

なんにせよ気兼ねなく自由に画像を書き出してそのまま使えるようになる時代になるといいですね。

おそまつ!

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

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

Cakephp2でボタンにクエリ付きのリンクを表示させたかった

ボタンっていう形を保ってクエリ付きのURLを生成させたかった。

他にもボタンの作り方はあってやり方はあるのだろうが、自分にとってはこの書き方が都合が良かったので記事にする。

コード

<?php
 //urlの生成
  $queries = ["id"=>$data['model']['id'], "name"=>$data['model']['name']];
  $url = $this->Html->url(['controller'=>'action', 'action'=>'action', "?"=>$queries]); 
?>
<!-- ボタン生成 -->
<button type="button" onclick="location.href='<?= $url ?>'">button</button>

FormHelper - 2.x
実際に書いてみると、何に悩んでいたのかわからないレベルに当然っちゃ当然だなって感じになった。

サンプルコード

<?php
/* Controller.php */
public function index(){
 //仮のデータ
 $datas = array(
     0 => array(
         'model' => array(
             'id' => 0,
             'name' => 'zero'
         ),
     ),
     1 => array(
         'model' => array(
             'id' => 1,
             'name' => 'one'
         ),
     ),
     2 => array(
         'model' => array(
             'id' => 2,
             'name' => 'two'
         ),
     ), 
  );
  $this->set('datas', $datas);
}

?>

<!-- view.ctp -->
<table>
    <tr>
        <th>id</th>
        <th>name</th>
        <th>buttons</th>
    </tr>
    <?php foreach($datas as $data): ?>
        <tr>
            <?php
                $queries = ["id"=>$data['model']['id'], "name"=>$data['model']['name']];
                $url = $this->Html->url(['controller'=>'controller', 'action'=>'action', "?"=>$queries]); 
            ?>

            <td><?= $data['model']['id'] ?></td>
            <td><?= $data['model']['name'] ?></td>
            <td><button type="button" onclick="location.href='<?= $url ?>'">button</button></td>
        </tr>
    <?php endforeach; ?>
</table>

実行結果

スクリーンショット 2020-10-24 20.46.26.png
上記のサンプルコードはこのような表となって出力されるはず。

スクリーンショット 2020-10-24 20.47.19.png
ボタン要素には、リンクが生成されてそこから飛ぶようになってる事が確認できた。

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

【超簡単】Firebase で無料で作るハイスコアDB

前回までの砂漠のひつじ

無料プログラム学習用ピコピコゲーム砂漠のひつじを作成しつつ、その過程を記事にしている。
本記事はハイスコア実装編4回目として、無料DBの選定、調査の経過として、Firebaseアカウント作成から簡単なDB操作までを行っている。

前回までの記事では、Azure CosmosDBの動作を一通り確認しアーキテクチャが必要以上に複雑と感じFirebaseを調査することとしていた。

前回までの記事:
- Azure Cosmos で無料で作るハイスコアDB(1)
- Azure Cosmos で無料で作るハイスコアDB(2) : APIとデータモデルとAzureテーブル
- Azure Cosmos で無料で作るハイスコアDB(3) : コア(SQL)

今回の調査を終えての結論を述べると、学習コスト / 利用しやすさは以下の様に感じた。

Firebase Cloud Firestore(簡単) << AWS DynamoDB <<<(超えられない壁)<< Azure CosmosDB(難しい)

以下、Firebase登録から、レコード登録、取得までを解説する。

Firebaseアカウント登録

Googleアカウントを持っていれば、一切情報入力なしで一瞬で登録完了する。

Firebase:料金ページのファビュラスではなくジェネラスなリミットのSparkプランの項目の内容に目を通して、「無料Sparkプラン」項目にある[すぐに開始可能]ボタンを押下。

00_firebase_register.png

プロジェクト作成

Firebaseアカウント登録が完了したらコンソールへ移動。
[プロジェクトを追加]ボタンを押下しプロジェクトを作成する。

プロジェクト名を入力し、GoogleAnalyticsの利用設定を行えば完了。
無料プロジェクトの作業はアクセス数ぐらいしかモチベーションがないので利用する設定にしておいたが、画面キャプチャは省略している。

10_firebase_console.png
20_firebase_project_01.png

DB設定

Cloud Firestore

プロジェクトの作成が終わったら、プロジェクトHome画面左のナビゲーションバーよりCloud Firestore を選択し、[データベースの作成]を押下し、任意の名前のデータベースを作成する。

30_cloud_firestore.png

作成時、テストモードにするとガバガバになるので注意が必要。

31_cloud_firestore_test.png

ロケーションは、asia-northeast1を選択。

32_cloud_firestore_location.png

コレクションを開始

RDBで言うところのテーブルに相当するのがFirebaseのコレクション。
コレクション登録時にレコードを1件登録するUIになっているのは賛否ありそうだが個人的にはよいと感じた。

40_db.png

レコード登録時にドキュメントIDを省略すると自動で一意のIDが振られるのも好印象。

41_db_collection.png
42_db_collection.png

アプリ設定

アプリ作成

今回はWebページで利用するので、プロジェクトのHome画面より、[</>]ボタン押下。
任意のアプリの名前をつける。

50_app.png
51_app2.png

※「このアプリのFirebase Hostingも設定します。」について
Firebase Hosting を使うと Firebase CLI の設定が簡単になったりするがお高い模様。
今回はCDNからFirebaseのライブラリを取得しており、GitHub Pagesで公開しているのでいずれにしてもチェックはしない。

html に初期化コード追加

初期化コードが出力されるので、htmlにコピペする。

53_app3.png

コメントにTODOの記載がある通り、firestoreにアクセスするためライブラリを追加する。

index.html
<!-- firebase
執筆時点バージョンは、7.24.0。ドキュメントによりバージョン番号が異なる。
コンパネで取得できた初期化コードのバージョンに合わせるのがよさそう。
-->
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-analytics.js"></script>

<!-- 利用したい機能を追加 -->
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-firestore.js"></script>

<!-- 初期化部分は別ファイルにしておく -->
<script src="./firebase/init-firebase.js"></script>
<!-- firebase -->

スコア登録処理(js)

collection名を指定して、add。
CosmosDBでやってた作業はなんだったのか。

sample.js
var db = firebase.firestore();
db.collection('scores').add({
    name: 'name',
    score: 1000
}).then((r) => {
    console.log(r); // 登録成功したレコードの内容を表示。r.id に一意のIDが設定されている。
}).catch((err) => {
    console.log(err);   // エラー内容を表示
})

スコア取得処理(js)

コレクションに対して、where, orderBy, limit を指定して任意のレコード取得可能。
get()で全件取得も可能。

sample.js
// Queryを作る。where 句も対応しているが今回は不要のため未実装。
var q = db.collection('scores').orderBy('score', 'desc').limit(5);

// 非同期で取得。docsに配列形式で格納されており、.data() で json オブジェクトを取得できる。
q.get().then((r) => {
    for(var d of r.docs) {
        console.log(d.data());
    }
})

おわりに

簡単過ぎてビックリしました。

apiKeyをさらすことには一抹の不安がありましたが、以下記事によると大丈夫そうなので安心しました。
Firebase apiKey ってさらしていいの? ほんとに?

次回は実際にアプリに組み込もうかと思います。

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

【超簡単】Firebase で無料で作るハイスコアDB : APIキー制限設定忘れずに!!

前回までの砂漠のひつじ

無料プログラム学習用ピコピコゲーム砂漠のひつじを作成しつつ、その過程を記事にしている。
本記事はハイスコア実装編4回目として、無料DBの選定、調査の経過として、Firebaseアカウント作成から簡単なDB操作までを行っている。

前回までの記事では、Azure CosmosDBの動作を一通り確認しアーキテクチャが必要以上に複雑と感じFirebaseを調査することとしていた。

前回までの記事:
- Azure Cosmos で無料で作るハイスコアDB(1)
- Azure Cosmos で無料で作るハイスコアDB(2) : APIとデータモデルとAzureテーブル
- Azure Cosmos で無料で作るハイスコアDB(3) : コア(SQL)

今回の調査を終えての結論を述べると、学習コスト / 利用しやすさは以下の様に感じた。

Firebase Cloud Firestore(簡単) << AWS DynamoDB <<<(超えられない壁)<< Azure CosmosDB(難しい)

以下、Firebase登録から、レコード登録、取得およびAPIキー制限までを解説する。
APIキー制限を行わないと悪意のある第三者からアクセスし放題になるので注意が必要。

Firebaseアカウント登録

Googleアカウントを持っていれば、一切情報入力なしで一瞬で登録完了する。

Firebase:料金ページのファビュラスではなくジェネラスなリミットのSparkプランの項目の内容に目を通して、「無料Sparkプラン」項目にある[すぐに開始可能]ボタンを押下。

00_firebase_register.png

プロジェクト作成

Firebaseアカウント登録が完了したらコンソールへ移動。
[プロジェクトを追加]ボタンを押下しプロジェクトを作成する。

プロジェクト名を入力し、GoogleAnalyticsの利用設定を行えば完了。
無料プロジェクトの作業はアクセス数ぐらいしかモチベーションがないので利用する設定にしておいたが、画面キャプチャは省略している。

10_firebase_console.png
20_firebase_project_01.png

DB設定

Cloud Firestore

プロジェクトの作成が終わったら、プロジェクトHome画面左のナビゲーションバーよりCloud Firestore を選択し、[データベースの作成]を押下し、任意の名前のデータベースを作成する。

30_cloud_firestore.png

作成時、テストモードにするとガバガバになるので注意が必要。

31_cloud_firestore_test.png

ロケーションは、asia-northeast1を選択。

32_cloud_firestore_location.png

コレクションを開始

RDBで言うところのテーブルに相当するのがFirebaseのコレクション。
コレクション登録時にレコードを1件登録するUIになっているのは賛否ありそうだが個人的にはよいと感じた。

40_db.png

レコード登録時にドキュメントIDを省略すると自動で一意のIDが振られるのも好印象。

41_db_collection.png
42_db_collection.png

アプリ設定

アプリ作成

今回はWebページで利用するので、プロジェクトのHome画面より、[</>]ボタン押下。
任意のアプリの名前をつける。

50_app.png
51_app2.png

※「このアプリのFirebase Hostingも設定します。」について
Firebase Hosting を使うと Firebase CLI の設定が簡単になったりするがお高い模様。
今回はCDNからFirebaseのライブラリを取得しており、GitHub Pagesで公開しているのでいずれにしてもチェックはしない。

html に初期化コード追加

初期化コードが出力されるので、htmlにコピペする。

53_app3.png

コメントにTODOの記載がある通り、firestoreにアクセスするためライブラリを追加する。

index.html
<!-- firebase
執筆時点バージョンは、7.24.0。ドキュメントによりバージョン番号が異なる。
コンパネで取得できた初期化コードのバージョンに合わせるのがよさそう。
-->
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-analytics.js"></script>

<!-- 利用したい機能を追加 -->
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.24.0/firebase-firestore.js"></script>

<!-- 初期化部分は別ファイルにしておく -->
<script src="./firebase/init-firebase.js"></script>
<!-- firebase -->

スコア登録処理(js)

collection名を指定して、add。
CosmosDBでやってた作業はなんだったのか。

sample.js
var db = firebase.firestore();
db.collection('scores').add({
    name: 'name',
    score: 1000
}).then((r) => {
    console.log(r); // 登録成功したレコードの内容を表示。r.id に一意のIDが設定されている。
}).catch((err) => {
    console.log(err);   // エラー内容を表示
})

スコア取得処理(js)

コレクションに対して、where, orderBy, limit を指定して任意のレコード取得可能。
get()で全件取得も可能。

sample.js
// Queryを作る。where 句も対応しているが今回は不要のため未実装。
var q = db.collection('scores').orderBy('score', 'desc').limit(5);

// 非同期で取得。docsに配列形式で格納されており、.data() で json オブジェクトを取得できる。
q.get().then((r) => {
    for(var d of r.docs) {
        console.log(d.data());
    }
})

APIキーに制限をかける【超重要】

勘の良い諸兄であれば、apiKeyを公開するソースに貼り付けてよいのか不安で作業が止まると思う。
推察の通りデフォルトではソースをコピペした第三者からアクセスし放題の状態となっている。

config.js
var firebaseConfig = {
    apiKey: "",
    authDomain: "",
    databaseURL: "",
    projectId: "",
    storageBucket: "",
    messagingSenderId: "",
    appId: "",
    measurementId: ""
};

ここまでの作業は画面の指示に従っていればできたのに、この作業だけなぜか一連のUIに組み込まれていない。よく分からないからFirebase Hosting を使おうと何度も挫けそうになった。

APIとサービスにアクセス

APIとサービス にアクセスし、現在作成中のプロジェクトを選択し、ナビゲーションより認証情報を選択すると、[Browser key (auto created by Firebase)]というAPIキーが警告と共に作成されているのが分かるのでこれをクリックする。

60_api1.png

アプリケーションの制限を設定

今回は、Git Hub Pages のURL(kaku3.github.io/the-sheep-in-the-desert/*)を、HTTPリファラー(ウェブサイト)として登録することにする。
この設定を行うと、デプロイ済みの本番環境からしか利用できなくなるので、アプリを2つ(prod, dev)作成し開発用のapiKeyは公開しないのがよさそうに思えた。

61_api2.png

おわりに

簡単過ぎてビックリしました。
APIキーがガバガバなのもびっくりしました。

次回は実際にアプリに組み込もうかと思います。

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

このサイトみたいの作りたい

http://kuromameshiba.com/

育毛剤のサイトかな

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

foreachで複数作ったbuttonタグでdivタグ全体をリンクにしてpostしたい!

こんにちは。クリスピーパンダです。
今回が初めての投稿ですが、早速行ってみましょう〜。

この記事で実現できること

foreach等のループ文で複数作ったform、divタグ、buttonタグで、buttonタグをdivタグ全体に広げて、リンク(button)を作成するものです。
イメージは、記事投稿サイトなどで記事表示する際に、たくさんできたカードの全体をボタンにして、postしようよって感じです。通常postはしないですが、ユーザーIDを送信したいよ!とかあるんで、そういう時に役立つ思います!

開発環境

OS:macOS Catalina
テキストエディタ:VSCode
フレームワーク:Laravel6
使用言語:HTML, CSS, JavaScript

実装

HTML

今回はLaravelなのでBladeですがHTMLと同じです。@foreachやroute('post.show')などはBladeでPHPを記述していますが、他のフレームワークでもループ文やaction先など指定すれば実装できます。

index.blade.php
@foreach($posts as $post)
  <form action="{{ route('post.show') }}" method="POST" name="post_show">
    <div class="linkbox">
      <p>{{ $post->title }}</p>
      <p>{{ $post->body }}</p>
      <input name="user_id" type="hidden" value="ここに送りたい値を記述">
      <button type="submit"></button>
    </div>
  </form>
@endforeach

これでpostのタイトルや内容が表示され、それを囲んでるdivタグ部分が次のCSSでリンク(ボタン)になります。
formタグ→divタグ→buttonタグの順番でコーディングしてください。

CSS

今回のHTML部分では、CSSの読み込みは省略していますが、CSSの読み込みも忘れずに行ってくださいね!

style.css
.linkbox {
    position: relative;
}
.linkbox button {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    /* buttonのスタイル削除 */
    background-color: transparent;
    border: none;
    cursor: pointer;
    outline: none;
    padding: 0;
    appearance: none;
}

まずはポジションを使用して、buttonタグを浮き上がらせて、buttonタグのスタイルをすべて削除することで、スケスケのbuttonタグが出来上がるというイメージです。

最後に

aタグで実装すればいいじゃん!と最初に思ったのですが、どうやらループ文で複数作成したaタグでpostすると、JavaScript等をかませないとだめみたいだったので、今回は簡単にbuttonタグで実装してみました。
aタグでもこんな感じで実装できるよ!やもっと簡単な方法あるよって方はぜひ教えて下さい!

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

【HTML】404ページを作成する方法

プログラミング勉強日記

2020年10月24日
404ページをカスタマイズする方法を初めて知ったのでまとめる。

404ページとは

 まず最初に404ページについて説明する。

  • 削除されたページにアクセスしたとき
  • 間違ったURLを入力したとき

 404ページは上記のように存在しないページにユーザがリンクしたときに表示されるエラーページのこと。サーバーにアクセスしたときの表示が404で処理されるので、404ページと呼ぶ。

Googleの例
image.png

GitHubの例
image.png

オリジナル404ページに記述する内容

 オリジナル404ページを作るポイントを紹介する。

  • サイトのデザインと統一性を持たせる
  • 次の行動を促すようにする

 例えば他のページが青を基調にしているのに対して404ページが赤を基調とすると統一性がなくなってしまう。なので、Webサイトのデザインと合わせることで唐突にエラー画面を出されたときに混乱を防ぐことができる。
 「ページが見つかりません」だけではユーザがどうすればいいかわかんなくなってしまうので、ページのサイトマップを入れたり、サイト内検索をできるようにしたり、ユーザに次の行動を促す必要がある。

オリジナルの404ページを表示させる方法

 .htaccessを使用する。.htaccessのファイルを作成して、404状態のときにどのページを表示するかという設定する。

image.png
 上の図のようにルートディレクトリに404.htmlを設置し、.htaccessに以下を記述する。

.htaccess
ErrorDocument 404 /404.html

 表示させるページのパスはルートパスで記述する。

参考文献

HTMLで404ページの作成方法を現役エンジニアが解説【初心者向け】
オリジナルな404(Not Found)ページの正しい作り方

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

Progate 初級編 通し模写

何も見ないで、模写した結果、ダメダメだった。

色は、macの基本ソフト digital color Meterを利用した。
このソフトを使えば、rgbが抽出できるので、それで、色をつけた。

HTMLは結構書き出せる様になった。
送信のrgbをつけないといけない
CSSの細かい部分,padding marginが全然書けない。

一応、全体的な模写.完璧を目指さずに大体できていればOK

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Progate</title>
    <link rel="stylesheet" href="./styles2.css">
    <header>
        <div class="header-wrapper">
        <div class="header-logo">Progate</div>
        <div class="header-nav">
        <ul>
            <li>プログラミングとは</li>
            <li>学べるレッスン</li>
            <li>お問い合わせ</li>
        </ul>
        </div>
        </div>
    </header>
    <main>
        <div class="contents-wrapper">
            <div class="hellow-h1">
                <h1>HELLO WORLD<span>.</span></h1>
            </div>
            <div class="welcome-h2">
                <h2>プログラミングの世界へようこそ</h2>
            </div>
            <div class="learn-h3">
                <h3>学べるレッスン</h3>
            </div>
        <div class="contents">
            <div class="contents-item">
                <img src="https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/html/study/html.svg">
                <p>HTML&CSS</p>
            </div>
            <div class="contents-item">
                <img src="https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/html/study/php.svg">
                <p>PHP</p>
            </div>
            <div class="contents-item">
                <img src="https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/html/study/ruby.svg">
                <p>Ruby</p>
            </div>
            <div class="contents-item">
                <img src="https://s3-ap-northeast-1.amazonaws.com/progate/shared/images/lesson/html/study/swift.svg">
                <p>Swift</p>
            </div>
        </div>
        </div>

        <div class="contact">
            <div class="contact-h3">
                <h3>お問い合わせ</h3>
            </div>
            <div class="contact-contents">
            <p>メールアドレス(必須)</p>
            <input>
            <p>お問い合わせ内容(必須)</p>
            <textarea></textarea>
            <p>※必須項目は必ずご入力ください</p>
            <input class="submit" type="submit" value="送信">
            </div>
        </div>

    </main>
    </footer>
        <div class="footer-wrapper">
        <div class="footer-logo">
            Progate
        </div>
        <div class="footer-nav">
            <ul>
                <li>会社概要</li>
                <li>採用</li>
                <li>Progate</li>
            </ul>
        </div>
        </div>
    </footer>

</head>
<body>
</body>
</html>

style.css

.header-wrapper{
    padding:30px;
    height:80px;
    background-color:rgb(99,205,200);
    color:white;
}

.header-logo{
    float:left;
    font-size:40px;
    padding:20px 20px;

}

.header-nav li{
    float:left;
    list-style:none;
    padding:30px;
    margin-bottom:40px;
}

.contents-wrapper{
    padding:40px;
}

.hellow-h1{
 font-size:40px;
}

.hellow-h1 span{
    color:red;
}

.welcome-h2{
    font-size:20px;
    padding-bottom:40px;
}

.learn-h3{
    font-size:16px;
    border-bottom:2px solid gray;
    margin-bottom:20px;
}

.contents{
    height:500px;
}

.contents-item{
    float:left;
    /*ここのheight*/
    margin-right:30px;
}

.contact{
    padding:30px;
    padding-bottom:30px;
}

.contact h3{
    border-bottom:1px solid rgb(224,231,235);
}

input,textarea{
    width:400px;
    /*答え見た margin*/
    margin-top:10px;
    margin-bottom:30px;

    padding:30px;
    /*答え見た周りがマイルドになる*/
    border:1px solid rgb(224,231,235);

}
.submit{
    background-color:rgb(224,231,235);
    /*答え見た文字が薄くなる*/
    color:rgb(144,161,173);
}



.footer-wrapper{
padding:20px;
height:200px;
background-color:rgb(55,81,101);
color:white;
}

.footer-logo{
    float:left;
    padding:40px 20px;
}

.footer-nav{
    float:right;
    padding:40px;
}

.footer-nav li{
    list-style:none;
    padding-bottom:20px;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ReactでPropsからHタグのレベルを変える。

?のようにPropsからHタグのレベルを制御したいとします。

<H level={1} /> // = <h1 />
<H level={2} /> // = <h2 />
<H level={3} /> // = <h3 />
<H level={4} /> // = <h4 />
<H level={5} /> // = <h5 />
<H level={6} /> // = <h6 />

React.ElementTypeにキャストすることで文字列からHTMLの標準タグを作ることができます。

解決法
function H(props) {
    const Header = `h${props.level}` as React.ElementType;
    return <Header />;
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む