Quantcast
Channel: CSSタグが付けられた新着記事 - Qiita
Viewing all 8498 articles
Browse latest View live

(´ω`) 箇条書き?樹形図にしたら見やすいっておっさんがいっとった

$
0
0

わいや。おっさんとはわいのことや。おっさんが言ったことの全てが間違っているとは思わんが確かに受け入れにくい"きもちわるさ"みたいなものを感じ取ったと思う。殺伐とした世の中で、そういう気持ちを忘れないで欲しい。そう思ってこの記事を書いたんだ。って前置きはそのぐらいにして今のとこ毎日書きまくってるな。書きなぐって丸めてぽいするブログみたいな感覚だ。マークダウンも##と```のハイライトしか使ってない。フォロワーが増えることはもうないと悟った。4記事目にして住人として世界の無常さを悟るが如く俺の書く記事ではフォロワーが増えないという事実の目の当たりにし愕然とした。希望などない。だから俺が希望になるよ。QIITAに変わるサービスを作ろうと思った。って前置きを入れて解説してくよ。

何作った

image.png

箇条書き。ってよく書くはずだ。学生でも社会人でも隣のおばちゃん家もそうさ。多分誰もが書く。1マス空けて。2マス開けて...それを樹形図に出来たら更に判りやすくなるんじゃねぇかな。って発想で作った。議事録もメモ程度なら箇条書きにする。するとこうなる...

縦に長くなる箇条書きより判りやすい

image.png

機能について

save tree imageを押せばSVG形式でダウンロードできる。
save indented textを押せばTXT形式でダウンロードできる。
木の高さも深さも調整可能だ。ドラッグでパンできてホイールでズームできる。
image.png
resize:bothしてあるおかげでウィンドウ自体も拡縮できる
ドッキングパネル化するフレームワークのおかげでエディタもビュアーも移動可能だ
image.png

利用しているライブラリ

入力/設定/出力とドッキングパネル化する (golden-layout)
テキストエリアをタブ入力可能にする (TabIndent.js)
ウィンドウのリサイズを検知する (resize-event)
箇条書きをjSON化する (indent2obj)

ソース

sample.html
<!doctype html><html><head><title></title><metacharset='utf-8'><metacontent=''name='author'><metacontent=''name='application-name'><metacontent=''name='description'><metacontent='telephone=no,address=no,email=no,date=no,url=no'name='format-detection'><metacontent='noimageindex,notranslate,nosnippet,noarchive,nofollow,noindex'name='robots'><metacontent='width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no'name='viewport'><linkhref='js/jquery/golden-layout/theme/base.css'rel='stylesheet'><linkhref='asset/manifest.json'rel='manifest'><linkhref='asset/favicon.ico'rel='icon'><style>@font-face{font-family:'M+2VM+IPAG circle';src:url('asset/m+2vm+ipag-circle.ttf');}html,body{margin:0;width:100%;height:100%;font-size:12px;}/*
      * 中央
      */main{top:50%;left:50%;position:absolute;transform:translate(-50%,-50%);}/*
      * 背景
      */.lm_goldenlayout.lm_content{background:white;}/*
      * 変更
      */main.wrap{width:80vw;height:80vh;resize:both;overflow:scroll;}/*
      * 見栄
      */main.wrap{border-bottom:2pxsolidrgba(34,36,38,.15);box-shadow:rgba(16,36,94,0.4)02px6px0;}/*
      * 設定
      */.proper.dg,.proper.dg.close-button{width:100%!important;}.proper.dg.main.close-button{display:none;}</style></head><body><main><divid='ui'class='wrap'></div></main></body></html><!-- native --><script src='js/native/d3-5.12.0.min.js'></script><script src='js/native/dat-gui/0.7.6.min.js'></script><script src='js/native/tab-indent-0.1.8.min.js'></script><script src='js/native/indent2obj-0.0.3.min.js'></script><!-- jquery --><script src='js/jquery/3.4.1.min.js'></script><script src='js/jquery/golden-layout/1.5.9.min.js'></script><script src='js/jquery/resize-event-1.2.1.min.js'></script><script>varapp={layout:{content:[{type:'row',content:[{width:29.3,type:'column',content:[{type:'component',componentName:'view',title:'editor'},{type:'component',componentName:'view',title:'proper'}]},{width:70.7,type:'stack',content:[{type:'component',componentName:'view',title:'viewer'}]}]}]},plugin:{editor:{elem:'<textarea></textarea>',option:{width:'100%',height:'100%',addClass:'tabIndent',css:{font:"12px 'M+2VM+IPAG circle",outline:'none',border:'none'}}},viewer:{elem:'<div></div>',option:{id:'svg',addClass:'tree',css:{background:'white'}}}},config:{save:function(){localStorage.setItem('tree',$editor.val())},download:function(){vardata=d3.select('svg').node().outerHTMLvarblob=newBlob([data])varlink=document.createElement("a")link.href=URL.createObjectURL(blob)link.download=newDate().toISOString()+'.svg'link.click()},height:0.3,width:11,}}var$ui=$('#ui')/*
    * 最低限
    */vardat=newdat.GUI({autoPlace:false})vargolden=newGoldenLayout(app.layout,$ui)// GOLDENを初期化()すると呼び出されるDOM挿入先の$コンテナを準備golden.registerComponent('view',function(container,state){varkey=container._config.title,ele=container.getElement()ele.addClass(key)golden[key]=ele})/*
    * 1.初期化
    */functioninit(){golden.init()}/*
    * DOM生成
    */var$editor=$(app.plugin.editor.elem,app.plugin.editor.option),$viewer=$(app.plugin.viewer.elem,app.plugin.viewer.option),$proper=$(this.dat.domElement)$editor.on('keyup',function(){update()})/*
    * 2.GOLDENにDOMを構築
    */functionconstruct(){// 生成したDOMを$コンテナに挿入golden['proper'].append($proper)golden['editor'].append($editor)golden['viewer'].append($viewer)}/*
    * 3.ビュアーをセットアップ
    */functionsetup(){dat.add(app.config,'height').onChange(update).name('tree height')dat.add(app.config,'width').onChange(update).name('tree width')dat.add(app.config,'download').name('save tree image')dat.add(app.config,'save').name('save indented text')$(window).on('resize',function(){golden.updateSize()})$ui.onResize({},function(){golden.updateSize()})}/*
    * ツリーはSVG
    */varview=d3.select($viewer.get(0)).append('svg')view.append('g')view.attr("xmlns","http://www.w3.org/2000/svg")view.append('style').text(`
             circle
             {
               stroke-width:2px;
               stroke:#05668D;
               fill:white;
               r:6;
             }
             text
             {
               font:12px 'M+2VM+IPAG circle';
             }
             rect
             {
               transform:translateY(-5px);
               stroke:#0cf;
               width:10px;
               heiht:10px;
               fill:white;
             }
             path
             {
               storke-width:2px;
               stroke:#ccc;
               fill:none;
             }
           `)functiongetLinks(arr){returnarr.enter().append('path').attr('d',d3.linkHorizontal().x(function(d){returnd.y}).y(function(d){returnd.x}))}functiongetNodes(arr){returnarr.enter().append('g').attr('class',function(d){return'node '+(d.children?'node--internal':'node--leaf')}).attr('transform',function(d){return"translate("+d.y+","+d.x+")";})}functionupdate(){varw=golden.viewer.width()varh=golden.viewer.height()view.attr('width',w).attr('height',h)varg=d3.select('svg > g')d3.select('svg > g').selectAll("*").remove()view.call(d3.zoom().on('zoom',function(){g.attr('transform',d3.event.transform)}))varvData=indent2obj($editor.val(),'\t')varvRoot=d3.hierarchy(vData[0]);varvNodes=vRoot.descendants();varvLayout=d3.tree().size([app.config.width*vNodes.reverse().length,app.config.height*h]);varvLinks=vLayout(vRoot).links();varmaxDepth=d3.max(vNodes,function(d){returnd.depth})varlinks=getLinks(g.selectAll('.link').data(vLinks))varnodes=getNodes(g.selectAll(".node").data(vNodes))nodes.append('circle')nodes.append('text').attr('dy','.35em').attr('x',function(d){returnd.children?-13:13;}).attr('text-anchor',function(d){returnd.children||d._children?'end':'start'}).text(function(d){returnd.data.name})}document.addEventListener('DOMContentLoaded',function(){init()construct()setup()if('tree'inlocalStorage){$editor.val(localStorage.getItem('tree'))update()}tabIndent.config.tab='\t';tabIndent.renderAll()})</script><style>@importurl('js/jquery/golden-layout/theme/light.css');@importurl('js/native/dat-gui/theme/light.min.css');</style/>

 備考

ウィンドウの陰影が恰好よくねぇ?


Styled-componentsでシンプルにグリッドレイアウトを実装する

$
0
0

はじめに

ReactとStyled-compomentsを使って、シンプルに12カラムのグリッドレイアウトを実装してみました。

カラムレイアウトにはFlexboxを使っています。
Reactの環境構築はcreate-react-appで行います。

なお、Styled-compomentsの概要については省略します。

グリッドレイアウトの概要

  • 12カラムのグリッドに沿って、横並びやレスポンシブのアイテムを配置していきます。
  • 各カラムの左右にはガター(溝)のpaddingがあります。12カラム全体では左右に(ガター/2)分のpaddingとなります。

グリッドレイアウトについてあまり聞きなれない場合は下記リンク等が参考になると思います。

Bootstrapのグリッドシステムの使い方を初心者に向けておさらいする
Grid system - Bootstrap 4.5 - 日本語リファレンス

1. Reactプロジェクトの準備

CRAをTypeScript付きでプロジェクト作成し、Styled-compoments関連のパッケージもインストールします。

$ npx create-react-app grid-layout-styled-components --typescript$ cd grid-layout-styled-components
$ npm install--save styled-components
$ npm install @types/styled-components
$ npm install--save-dev babel-plugin-styled-components

次にbabel-plugin-styled-componentsを使うための準備をします。

$ touch .babelrc

.babelrc

{"plugins":[["babel-plugin-styled-components"]]}

最後にindex.cssとApp.cssの中身を一旦空にしておきます。

2. グローバルスタイルの作成

グローバルに適用するスタイルを作成します。

$ touch src/GlobalStyle.ts

はじめにリセットCSSを追加します。好みによりNormalizeCSSでも可能だと思います。
リセットCSSの中では個人的にEric Meyer氏のものがシンプルで好きです。

GlobalStyle.ts
import{createGlobalStyle}from'styled-components/macro';exportconstGlobalStyle=createGlobalStyle`
  /* Reset CSS */
  /* ===================================== */

  /* http://meyerweb.com/eric/tools/css/reset/ 
    v2.0 | 20110126
    License: none (public domain)
  */

  html, body, div, span, applet, object, iframe,
  h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  a, abbr, acronym, address, big, cite, code,
  del, dfn, em, img, ins, kbd, q, s, samp,
  small, strike, strong, sub, sup, tt, var,
  b, u, i, center,
  dl, dt, dd, ol, ul, li,
  fieldset, form, label, legend,
  table, caption, tbody, tfoot, thead, tr, th, td,
  article, aside, canvas, details, embed, 
  figure, figcaption, footer, header, hgroup, 
  menu, nav, output, ruby, section, summary,
  time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
  }
  /* HTML5 display-role reset for older browsers */
  article, aside, details, figcaption, figure, 
  footer, header, hgroup, menu, nav, section {
    display: block;
  }
  body {
    line-height: 1;
  }
  ol, ul {
    list-style: none;
  }
  blockquote, q {
    quotes: none;
  }
  blockquote:before, blockquote:after,
  q:before, q:after {
    content: '';
    content: none;
  }
  table {
    border-collapse: collapse;
    border-spacing: 0;
  }
}
`;

次にタイプセレクタへのCSSを追加します。
ここで必須なのは*, *::before, *::after{box-sizing: border-box;}になります。

ついでに必要ないとは思いますが、フォントはいつでも綺麗にしておきたい性分なのでbodyへのfont-family設定も癖で追加しました。

GlobalStyle.ts
import{createGlobalStyle}from'styled-components/macro';exportconstGlobalStyle=createGlobalStyle`
  /* Reset CSS */
  /* ===================================== */

  /* http://meyerweb.com/eric/tools/css/reset/ 
    v2.0 | 20110126
    License: none (public domain)
  */

  html, body, div, span, applet, object, iframe,
  h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  a, abbr, acronym, address, big, cite, code,
  del, dfn, em, img, ins, kbd, q, s, samp,
  small, strike, strong, sub, sup, tt, var,
  b, u, i, center,
  dl, dt, dd, ol, ul, li,
  fieldset, form, label, legend,
  table, caption, tbody, tfoot, thead, tr, th, td,
  article, aside, canvas, details, embed, 
  figure, figcaption, footer, header, hgroup, 
  menu, nav, output, ruby, section, summary,
  time, mark, audio, video {
    margin: 0;
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
  }
  /* HTML5 display-role reset for older browsers */
  article, aside, details, figcaption, figure, 
  footer, header, hgroup, menu, nav, section {
    display: block;
  }
  body {
    line-height: 1;
  }
  ol, ul {
    list-style: none;
  }
  blockquote, q {
    quotes: none;
  }
  blockquote:before, blockquote:after,
  q:before, q:after {
    content: '';
    content: none;
  }
  table {
    border-collapse: collapse;
    border-spacing: 0;
  }

  /* Add Global CSS */
  /* ===================================== */

  *, *::before, *::after {
    box-sizing: border-box;
  }

  body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
  }
`;

3. 定数の作成

App.tsxに書いていきます。以下を用意します。

  • ブレークポイント
  • 各ブレークポイントに対応するコンテナの最大幅
  • グリッドの溝
  • カラム数
App.tsx
importReactfrom'react';importstyledfrom'styled-components/macro';import{GlobalStyle}from'./GlobalStyle';import'./App.css';// configsconstbreakpoints:{sm:number;md:number;lg:number;xl:number}={sm:576,md:768,lg:992,xl:1280,};constcontainerMaxWidths:{sm:number;md:number;lg:number;xl:number}={sm:540,md:720,lg:960,xl:1250,};constgridColumns:number=12;constgridGutterWidth:number=32;// componentsfunctionApp(){return<div><GlobalStyle/></div>;
}exportdefaultApp;

4. 汎用コンポーネント作成

汎用的に使うコンテナのコンポーネントと、グリッド行・グリッド列のコンポーネントを用意します。

実装にあたりBootstrapのscssやcssのソースを参考にしました。
全て理解するのは難解ですが、一つ一つは(Bootstrapを使うかに関係なく)CSSの設計に勉強になることが多いと感じます。

App.tsx
importReactfrom'react';importstyledfrom'styled-components/macro';import{GlobalStyle}from'./GlobalStyle';import'./App.css';// configsconstbreakpoints:{sm:number;md:number;lg:number;xl:number}={sm:576,md:768,lg:992,xl:1280,};constcontainerMaxWidths:{sm:number;md:number;lg:number;xl:number}={sm:540,md:720,lg:960,xl:1250,};constgridColumns:number=12;constgridGutterWidth:number=32;// componentsconstContainer=styled.div`
  max-width: 100%;
  @media (min-width: ${breakpoints.sm}px) {
    max-width: ${containerMaxWidths.sm}px;
  }
  @media (min-width: ${breakpoints.md}px) {
    max-width: ${containerMaxWidths.md}px;
  }
  @media (min-width: ${breakpoints.lg}px) {
    max-width: ${containerMaxWidths.lg}px;
  }
  @media (min-width: ${breakpoints.xl}px) {
    max-width: ${containerMaxWidths.xl}px;
  }
  padding-right: ${gridGutterWidth/2}px;
  padding-left: ${gridGutterWidth/2}px;
  margin-right: auto;
  margin-left: auto;
`;constRow=styled.div`
  display: flex;
  flex-wrap: wrap;
  margin-right: ${-gridGutterWidth/2}px;
  margin-left: ${-gridGutterWidth/2}px;
`;typeColProps={sizeDefault:number;sizeSm?:number;sizeMd?:number;sizeLg?:number;sizeXl?:number;};constCol=styled.div<ColProps>`
  flex: 0 0 ${(props)=>(props.sizeDefault/gridColumns)*100}%;
  max-width: ${(props)=>(props.sizeDefault/gridColumns)*100}%;
  @media (min-width: ${breakpoints.sm}px) {
    flex: 0 0 ${(props)=>((props.sizeSm||props.sizeDefault)/gridColumns)*100}%;
    max-width: ${(props)=>((props.sizeSm||props.sizeDefault)/gridColumns)*100}%;
  }
  @media (min-width: ${breakpoints.md}px) {
    flex: 0 0 ${(props)=>((props.sizeMd||props.sizeDefault)/gridColumns)*100}%;
    max-width: ${(props)=>((props.sizeMd||props.sizeDefault)/gridColumns)*100}%;
  }
  @media (min-width: ${breakpoints.lg}px) {
    flex: 0 0 ${(props)=>((props.sizeLg||props.sizeDefault)/gridColumns)*100}%;
    max-width: ${(props)=>((props.sizeLg||props.sizeDefault)/gridColumns)*100}%;
  }
  @media (min-width: ${breakpoints.xl}px) {
    flex: 0 0 ${(props)=>((props.sizeXl||props.sizeDefault)/gridColumns)*100}%;
    max-width: ${(props)=>((props.sizeXl||props.sizeDefault)/gridColumns)*100}%;
  }
  padding-right: ${gridGutterWidth/2}px;
  padding-left: ${gridGutterWidth/2}px;
`;functionApp(){return<div><GlobalStyle/></div>;
}exportdefaultApp;

ここで各コンポーネントの解説をします。
なお前提として、モバイルファーストで作っています。

Containerコンポーネント

幅はブレークポイントに対応する最大幅を設定します。
中央寄せした上で、グリッド溝/2を左右のpaddingに与えます。

Rowコンポーネント

はじめにdisplayflexにセットして、
グリッド溝/2のネガティブマージンを左右のmarginに与えます。

Colコンポーネント

幅は12グリッドのいくつ分を占めるかをpropsとして受け取れるようにします。
デフォルトの幅は必須で、sm/md/lg/xl用の幅は任意とします。

※sizeDefaultの名前は最初sizeとする予定だったのですが、元々HTMLにsizeという属性があるようなので止めました。

flexの他にmax-widthにおいても幅を設定していますが、前者だけだと特定ブラウザで動かないようなので後者も設定する必要があるらしいです。(Bootstrapのソースコメントによると)
この辺りは申し訳無いのですが調べずにスルーしています。

余談

なるべくシンプルにという方針で、多少1つのブロックにつき繰り返しは多くなりそうですが
css propを使わない(Sassでいうmixinのような用法)方針で実装しました。

5. 実際に使ってみる

前章のコンポーネントを使ってみます。
グリッドを適用する場合はRowを記述し、その子にColをサイズのpropsと共に指定します。

App.css
.side-border{border-right:1pxsolid#000;border-left:1pxsolid#000;}
App.tsx
importReactfrom'react';importstyledfrom'styled-components/macro';import{GlobalStyle}from'./GlobalStyle';import'./App.css';// configsconstbreakpoints:{sm:number;md:number;lg:number;xl:number}={sm:576,md:768,lg:992,xl:1280,};constcontainerMaxWidths:{sm:number;md:number;lg:number;xl:number}={sm:540,md:720,lg:960,xl:1250,};constgridColumns:number=12;constgridGutterWidth:number=32;// componentsconstContainer=styled.div`
  max-width: 100%;
  @media (min-width: ${breakpoints.sm}px) {
    max-width: ${containerMaxWidths.sm}px;
  }
  @media (min-width: ${breakpoints.md}px) {
    max-width: ${containerMaxWidths.md}px;
  }
  @media (min-width: ${breakpoints.lg}px) {
    max-width: ${containerMaxWidths.lg}px;
  }
  @media (min-width: ${breakpoints.xl}px) {
    max-width: ${containerMaxWidths.xl}px;
  }
  padding-right: ${gridGutterWidth/2}px;
  padding-left: ${gridGutterWidth/2}px;
  margin-right: auto;
  margin-left: auto;
`;constRow=styled.div`
  display: flex;
  flex-wrap: wrap;
  margin-right: ${-gridGutterWidth/2}px;
  margin-left: ${-gridGutterWidth/2}px;
`;typeColProps={sizeDefault:number;sizeSm?:number;sizeMd?:number;sizeLg?:number;sizeXl?:number;};constCol=styled.div<ColProps>`
  flex: 0 0 ${(props)=>(props.sizeDefault/gridColumns)*100}%;
  max-width: ${(props)=>(props.sizeDefault/gridColumns)*100}%;
  @media (min-width: ${breakpoints.sm}px) {
    flex: 0 0 ${(props)=>((props.sizeSm||props.sizeDefault)/gridColumns)*100}%;
    max-width: ${(props)=>((props.sizeSm||props.sizeDefault)/gridColumns)*100}%;
  }
  @media (min-width: ${breakpoints.md}px) {
    flex: 0 0 ${(props)=>((props.sizeMd||props.sizeDefault)/gridColumns)*100}%;
    max-width: ${(props)=>((props.sizeMd||props.sizeDefault)/gridColumns)*100}%;
  }
  @media (min-width: ${breakpoints.lg}px) {
    flex: 0 0 ${(props)=>((props.sizeLg||props.sizeDefault)/gridColumns)*100}%;
    max-width: ${(props)=>((props.sizeLg||props.sizeDefault)/gridColumns)*100}%;
  }
  @media (min-width: ${breakpoints.xl}px) {
    flex: 0 0 ${(props)=>((props.sizeXl||props.sizeDefault)/gridColumns)*100}%;
    max-width: ${(props)=>((props.sizeXl||props.sizeDefault)/gridColumns)*100}%;
  }
  padding-right: ${gridGutterWidth/2}px;
  padding-left: ${gridGutterWidth/2}px;
`;// UsageconstHeading=styled.h1`
  font-size: 32px;
  font-weight: bold;
  padding: 24px 0;
`;typeInnerContentProps={height:number;backgroundColor:string};constInnerContent=styled.div<InnerContentProps>`
  height: ${(props)=>props.height}px;
  background-color: ${(props)=>props.backgroundColor};
`;functionApp(){return(<div><GlobalStyle/><ContainerclassName="side-border"><Heading>12Gridsystem</Heading>
<Row>{[0,1,2,3,4,5,6,7,8,9,10,11].map((v,index)=>(<Colkey={index}sizeDefault={1}><InnerContentheight={600}backgroundColor="deepskyblue"></InnerContent>
</Col>
))}</Row>
<Heading>Responsive1</Heading>
<Row><ColsizeDefault={12}sizeMd={4}sizeLg={4}sizeXl={4}><InnerContentheight={200}backgroundColor="lightgray"></InnerContent>
</Col>
<ColsizeDefault={12}sizeMd={4}sizeLg={4}sizeXl={4}><InnerContentheight={200}backgroundColor="darkgray"></InnerContent>
</Col>
<ColsizeDefault={12}sizeMd={4}sizeLg={4}sizeXl={4}><InnerContentheight={200}backgroundColor="gray"></InnerContent>
</Col>
</Row>
<Heading>Responsive2</Heading>
<Row><ColsizeDefault={12}sizeMd={12}sizeLg={4}sizeXl={4}><InnerContentheight={300}backgroundColor="gold"></InnerContent>
</Col>
<ColsizeDefault={12}sizeMd={12}sizeLg={8}sizeXl={8}><InnerContentheight={300}backgroundColor="goldenrod"></InnerContent>
</Col>
</Row>
<Heading>Responsive3</Heading>
<Row><ColsizeDefault={12}sizeLg={8}sizeXl={8}><Row><ColsizeDefault={6}><InnerContentheight={150}backgroundColor="blue"></InnerContent>
</Col>
<ColsizeDefault={6}><InnerContentheight={150}backgroundColor="darkblue"></InnerContent>
</Col>
<ColsizeDefault={6}><InnerContentheight={150}backgroundColor="dodgerblue"></InnerContent>
</Col>
<ColsizeDefault={6}><InnerContentheight={150}backgroundColor="royalblue"></InnerContent>
</Col>
</Row>
</Col>
<ColsizeDefault={12}sizeLg={4}sizeXl={4}><InnerContentheight={300}backgroundColor="crimson"></InnerContent>
</Col>
</Row>
</Container>
</div>
);}exportdefaultApp;

上記を出力するとこのようになります。

スクリーンショット 2020-09-25 7.20.16.png

実際の動きは下記GitHubからリンクを参照してください。

https://github.com/yha-1228/grid-layout-styled-components

社会行動リズム表アプリを作成する【作成中】

displayとpositionの不思議な関係

$
0
0

inline要素にposition: absoluteを指定すると自動的にdisplay:blockになることに気づいたので他のpositionプロパティだとどうなるの?って感じで調べてみた。(常識? w3cのドキュメントに書いてあるのかもしれないけど見てない)

position: absoluteposition: fixedの場合にdisplayプロパティの変化が起こる模様

inline<-> block
inline-flex<-> flex
inline-table<-> table
...

全部のdisplayプロパティは調べてません。

https://jsfiddle.net/cojtu8rL/61/

Tyハロトレ27日目

$
0
0

CSS

repeat-x

bgrepeatx2.png

bg-attachment

bgattachment2.png

bg-size

bg-size2.png

ショートハンド

shorthand2.png

拡張子

png・・・可逆圧縮(元に戻せまっせ)
jpeg・・・データを一部捨てているので、不可逆的圧縮(元に戻せんわい)
gif・・・べた塗りのイラストによく使います。

bdrs

bdrs2.png

text-shadow

h1{text-shadow:x方向の距離y方向の距離ぼかし幅影色;}

tShadow3.png

box-shadow

h1{box-shadow:x方向の距離y方向の距離ぼかし幅(広がり)影色(内側指定);}

「rgba」の最後の「a」はアルファ値(alpha)で不透明度を表すのによく使います。

box-shadow2.png

linear-gradient

線形グラデーションを表します。radial-gradientは、円形グラデーションを表します。
 to bottomは下方向へという意味になります。

h1{background-image:linear-gradient(開始位置(xxx方向へ),開始色,終了色);}

linear-gradient2.png

Google Fonts

limelight.png

index.html
<linkhref="https://fonts.googleapis.com/css2?family=Limelight&display=swap"rel="stylesheet">
style.css
h1{font-family:'Limelight',cursive;}

googleFonts2.png

Photoshop

ショートカット

Ctrl + スペースキーでズーム

スクロール

フィルター>その他>スクロール
スクロール.png

スクロール32.png

色調補正

イメージ>色調補正>色相・彩度
色調補正2.png

選択ツール

選択ツールにあるマークは、マジックワンド wand なので、ショートカット「w」キー
Ctrl + D で選択解除

切り抜きコピー

切り抜きコピー2.png

透明な部分を編集できないようにする

透明な部分を編集できない3.png

塗りつぶし

塗りつぶし.png

ぼかし(ガウス)

フィルター>ぼかし>ぼかし(ガウス)
スクリーンショット 2020-09-26 11.10.50.png

影の色を調節

スクリーンショット 2020-09-26 11.23.21.png

遠近法

編集>変形>遠近法
平行に2.png

ワープ

編集>変形>ワープ
ペンツールみたいに操作します。
ワープペン2.png

乗算

白じゃないときは、画像を切り抜くしかないです。
乗算.png

自由な形に

自由な形に.png

半分を選択

選択範囲をカットしたレイヤー.png

Ai(ベクトル) →  Ps(ビットマップ)
        変換
illustratorのレイヤーを全て選択してコピー
Photoshopに貼り付けすると、下記画像のような画面が出て、ピクセルを選びます。
イラレから.png
illustratorのファイルも画像と同じように加工できます。
スクリーンショット 2020-09-26 11.50.00.png

ガイドをロック

ガイドを間違えて消してしまわないように、
ガイドをロックするとはかどります。
ガイドをロック.png

amp-img から学ぶ画像の表示のベストプラクティス

$
0
0

AMPは Google が推奨しているウェブコンポーネントフレームワークで、その実装には Web サイトのパフォーマンスを向上させるための知見が詰まっています。
AMP コンポーネントの実装を詳しく見ていくと、 AMP を導入せずにサイトを作る際にも役に立つベストプラクティスを学べるのではないかと思います。
以下では amp-imgコンポーネントに注目して web サイト開発における画像表示の実装について掘り下げます。

amp-img

amp-img は AMP 対応のサイトで画像を表示する際に、 HTML の img タグの代わりに使用します。
AMP の built-in 要素であるため、 amp-img 専用の js を追加で読む必要はなく、AMP のランタイムを通して自動的に使用できます。

amp-img の基本の使い方

<amp-imgsrc="/static/sample.jpg"width="1080"height="720"layout="fixed"alt="sample"></amp-img>

参考

画面の解像度に合わせた画像を表示

HTML の img タグと同様に amp-img タグでもsrcset属性や size属性を使用することができます。
高解像度の画面(Retina ディスプレイなど)で高解像な画像を配信する場合きれいな画像を表示できるメリットがありますが、低解像度の画面でも必要以上に重い画像を時間をかけて読み込まなくてはなりません。
srcset属性や size属性を使用することで、画面の解像度に合わせて適切な画像を表示することができます。

<amp-imgalt="sample"src="/static/sample-640.jpg"width="640"height="400"srcset="/static/sample-640.jpg 640w,
          /static/sample-320.jpg 320w"sizes="(min-width: 650px) 50vw, 100vw"></amp-img>

アートディレクション

ブレークポイントの条件に合わせて画像を変更することをアートディレクションと言います。
amp-img では media属性によってブレークポイントを指定して画像自体を切り替えることができます。
srcset属性 と size属性による画像の切り替えは、基本的に解像度のみ異なる同一の画像を切り替えることが想定されていますが、media属性の場合は画像のアスペクト比が異なっていても問題ありません。

<amp-imgalt="sample"media="(max-width: 768px)"width="226"height="340"src="/static/sample-medium.jpg"></amp-img><amp-imgalt="sample"media="(mim-width: 769px)"width="450"height="340"src="/static/sample-small.jpg"></amp-img>

通常の HTML タグでアートディレクションを実現する場合、picture タグを使用します。1

<picture><sourcesrcset="/static/sample-medium.jpg"media="(max-width: 768px)"><sourcesrcset="/static/sample-small.jpg"media="(mim-width: 769px)"><imgsrc="/static/sample-small.jpg"alt="sample"></picture>

参考

遅延ロード

画像の遅延ロードは、画面に表示されていない画像は読み込まずに、画面のスクロールに応じてあとから画像を読み込むことでウェブページの表示を高速化する手法です。
通常の img タグを使用した場合、ページアクセス時にすべての img タグの画像を読み込みます。
これによりページが最低限の操作を受け付けるようになるまでに時間がかかってしまったり、スクロールしない場合に不要な通信が発生したり、といったことが起きます。

amp-img は画面のスクロール位置に応じて、amp-img タグ内に img タグを生成します。この時に初めて画像の取得のための通信が発生するため効率的に画像をロードすることができます。

<amp-imgsrc="/static/sample.jpg"width="1080"height="720"layout="fixed"alt="sample"></amp-img>

<amp-imgsrc="/static/sample.jpg"width="1080"height="720"layout="fixed"alt="sample"class="i-amphtml-element i-amphtml-layout-fixed i-amphtml-layout-size-defined i-amphtml-layout"i-amphtml-layout="fixed"style="width: 1080px; height: 610px;"><imgdecoding="async"alt="sample"src="/static/sample.jpg"class="i-amphtml-fill-content i-amphtml-replaced-content"></amp-img>

amp-img を使用せずに遅延ロードを行う場合、スクラッチで実装するほか、lazyloadなどのライブラリの利用や、img タグの loading 属性を使用する方法があります。(ただし、Safari と IE11 は未対応

非同期で画像をデコード

展開されたコードの img タグを見ると、decoding="async"の指定があります。
画像データは通常ファイルサイズを小さくするためにエンコードされているため、ブラウザは画像を表示する際はデータをデコードする必要があります。
img タグに decoding属性によってブラウザに同期/非同期のどちらでデコードするかのヒントを提供でき、全てのモダンブラウザに対応しています。1
decoding属性に指定できる値は下記の通りです。

説明
sync画像を同期的にデコードする
async画像を非同期でデコードする
auto優先設定なし(デフォルト値)

amp-img コンポーネントは、img タグにdecoding="async"を付与することで、メインスレッドの処理をブロックせずに画像を非同期的にデコードさせています。

参考

画像のフォールバック

amp-img では、例えば webp の画像を使用する際に、webp 未対応のブラウザ用に jpg の画像を設定したい場合など、画像の読み込みに失敗した際のフォールバック画像を指定することができます。

<amp-imgalt="sample"width="1080"height="720"src="/static/sample.webp"><amp-imgalt="sample"fallbackwidth="1080"height="720"src="/static/samples.jpg"></amp-img></amp-img>

amp-img を使用しない場合、picture タグを使用することで実現できます。

<picture><sourcetype="image/webp"srcset="/static/sample.webp"/> // wepb 対応の場合は source タグの画像を提供
  <imgsrc="/static/samples.jpg"width="1080"height="720"alt="sample"/>  // wepb 未対応ブラウザで source タグの画像を提供できない場合の代替画像
</picture>

参考
- 画像要素 - HTML: HyperText Markup Language | MDN

レイアウトシフト対策

Google の提唱する UX 指標である Core Web Vitalsの一つに Cumulative Layout Shift(CLS)があります。
これは予期せぬレイアウトのズレや崩れを独自に指標化し評価しているもので、画像が読み込まれた際のこのレイアウトの移動によってスコアが下がってしまいます。
amp-img コンポーネントは、画面幅によって画像の幅 / 高さが変化しない場合、画像を表示する明示的なサイズを widthheightに指定することで amp-img のインラインスタイルとして展開され、レイアウト時に画像の表示領域が確保されます。2
画面幅によって画像の表示サイズが変化する場合は、適切なスタイルを付与することによりレイアウトシフトを防いでいます(後述)。

通常の img タグの場合もwidth / height属性への値を指定や、CSS でwidth / heightに具体値を指定することで画像を読み込む前に場所を確保し、レイアウトシフトを防ぐことができます。
2019 年 10 月に WHATWG が img タグの widht / height属性に基づいてデフォルトのアスペクト比を設定できる仕様が標準化されました。
そのため現在のモダンブラウザでは、画面の幅によって画像の表示サイズが変化するレスポンシブな表示でも widthheight利用してレイアウトシフトを防ぐことができます。

例えば、下記のようにな img タグを設置した場合、3 : 2 のアスペクト比でブラウザが表示場所を計算して確保してくれます。

<imgsrc="/static/samples.jpg"width="1080"height="720"alt="sample">
img{width:100%;height:auto;}

参考

レスポンシブ対応のスタイル

layout 属性

amp-img コンポーネントは layout属性を指定することにより、AMP のレイアウトシステムを利用できます。
layout属性は AMP コンポーネント共通の属性ですが、コンポーネントによってサポートされる値が異なります。
amp-img コンポーネントは container以外の下記のレイアウトに対応しています。

  • fill
  • fixed
  • fixed-height
  • responsive
  • flex-item
  • intrinsic
  • nodisplay

amp-img タグとその子要素の img タグには、layout属性の指定に応じた class が指定されます。
レスポンシブ対応をする際に、ウインドウや親のコンテンツのサイズの変化に伴ってどのように画像の表示を変化させるのかは往々にして悩ましいものです。
そんな時に layout属性による画像を様々な表示パターンとそのスタイルは参考になります。
下記ではそれぞれの layoutの値を amp-img に指定した場合のスタイルを詳しく見ていきます。
なお、layout属性は amp-img 専用の属性ではなく、AMP コンポーネント共通のものであるため、画像以外のコンテンツにも応用できます。
layout値を指定した際のアニメーション画像は公式ドキュメントからお借りしました。

参考

layout="fill"

親要素のコンテンツボックス全体を埋めるように拡大縮小されます。
widthheightに指定したアスペクト比が親要素のアスペクト比と合わない場合は引き伸ばされて表示されます。
fill.gif

<amp-imgsrc="/static/samples.jpg"width="1080"height="720"layout="fill"alt="sample"></amp-img>

↓ 画像ロード後

<amp-imgsrc="/static/samples.jpg"layout="fill"alt="sample"class="i-amphtml-element i-amphtml-layout-fill i-amphtml-layout-size-defined i-amphtml-layout"i-amphtml-layout="fill"style="--loader-delay-offset:434ms !important;"><imgdecoding="async"alt="sample"src="/static/samples.jpg"class="i-amphtml-fill-content i-amphtml-replaced-content"></amp-img>
/* amp-img タグのスタイル */.i-amphtml-layout-size-defined{overflow:hidden!important;}.i-amphtml-layout-fixed{display:block;overflow:hidden!important;/* .i-amphtml-layout-size-defined のスタイルによって打ち消される */position:absolute;top:0;left:0;bottom:0;right:0;}/* img タグのスタイル */.i-amphtml-layout-size-defined.i-amphtml-fill-content{position:absolute;top:0;left:0;bottom:0;right:0;}.i-amphtml-replaced-content{padding:0!important;border:none!important;}.i-amphtml-replaced-content{padding:0!important;border:none!important;}.i-amphtml-fill-content{display:block;height:0;max-height:100%;max-width:100%;min-height:100%;min-width:100%;width:0;margin:auto;}

amp-img タグは .i-amphtml-layout-fixedに指定されているスタイルにより、position: absolute;であるため、直近のposition: static;以外の positionの値を持つ親要素の上下左右いっぱいに広がるように表示されます。

img タグは .i-amphtml-layout-size-defined .i-amphtml-fill-contentに指定されているスタイルにより、直近のposition: static;以外の positionの値を持つ親要素、つまり amp-img の上下左右いっぱいに広がるように表示されます。
img が amp-img のサイズいっぱいになる構造は、どの layoutを指定した場合でも共通しています。
layout="fill"の場合は amp-img タグと img タグが共にposition: absolute;であるため、基準となる親要素に高さを明示的に指定する必要があります。

.i-amphtml-replaced-contentに指定されているスタイルは、ユーザーエージェントスタイルを打ち消すためのスタイルです。
また、.i-amphtml-fill-contentに指定されているスタイルは、iOS で iframe をレスポンシブ対応させる際にコンテンツのサイズをコンテナーに収めるための指定のようです。(issue)
layout属性は他のコンポーネントでも使用されるため、amp-img タグの場合でもこのようなスタイルが適応されます。
これらのスタイルは他の layout値を指定した場合でも登場しますが、今回の内容には直接関係ないため以下では割愛します。

layout="fixed"

ウインドウのサイズが変化しても画像の大きさは変化せず、widthheight属性に基づいて固定の寸法のまま表示されます。

fixed.gif

<amp-imgsrc="/static/samples.jpg"width="1080"height="720"layout="fixed"alt="sample"></amp-img>

↓ 画像ロード後

<amp-imgsrc="/static/samples.jpg"width="1080"height="720"layout="fixed"alt="sample"class="i-amphtml-element i-amphtml-layout-fixed i-amphtml-layout-size-defined i-amphtml-layout"i-amphtml-layout="fixed"style="width: 1080px; height: 610px; --loader-delay-offset:226ms !important;"><imgdecoding="async"alt="sample"src="/static/samples.jpg"class="i-amphtml-fill-content i-amphtml-replaced-content"></amp-img>
/* amp-img タグのスタイル */element.style{width:1080px;height:610px;--loader-delay-offset:188ms!important;}.i-amphtml-layout-size-defined{overflow:hidden!important;}.i-amphtml-layout-fixed{display:inline-block;position:relative;}

amp-img タグにはインラインスタイルとして widthheight属性で指定した値が指定されています。
overflow: hidden;が指定されているため、画像の表示サイズよりウインドウが小さくなった場合もスクロールは発生せずに画像は見切れて表示されます。

layout="fixed-height"

高さは固定のまま、幅は使用可能なスペースに合わせて広がります。

fixed-height.gif

<amp-imgsrc="/static/samples.jpg"height="720"layout="fixed-height"alt="sample"></amp-img>

↓ 画像ロード後

<amp-imgsrc="/static/samples.jpg"layout="fixed-height"height="720"alt="sample"class="i-amphtml-element i-amphtml-layout-fixed-height i-amphtml-layout-size-defined i-amphtml-layout"i-amphtml-layout="fixed-height"style="height: 720px; --loader-delay-offset:377ms !important;"><imgdecoding="async"alt="sample"src="/static/samples.jpg"class="i-amphtml-fill-content i-amphtml-replaced-content"></amp-img>
/* amp-img タグのスタイル */element.style{height:720px;}.i-amphtml-layout-size-defined{overflow:hidden!important;}.i-amphtml-layout-fixed-height{display:block;position:relative;}

layout="responsive"

width / height属性で指定されたアスペクト比を維持したまま、使用可能なスペースに合わせて拡大・縮小します。

responsive.gif

<amp-imgsrc="/static/samples.jpg"width="1080"height="720"layout="responsive"alt="sample"></amp-img>

↓ 画像ロード後

<amp-imgsrc="/static/samples.jpg"layout="fixed-height"height="720"alt="sample"class="i-amphtml-element i-amphtml-layout-fixed-height i-amphtml-layout-size-defined i-amphtml-layout"i-amphtml-layout="fixed-height"style="--loader-delay-offset:377ms !important;"><i-amphtml-sizerslot="i-amphtml-svc"style="padding-top: 66.6667%;"></i-amphtml-sizer><imgdecoding="async"alt="sample"src="/static/samples.jpg"class="i-amphtml-fill-content i-amphtml-replaced-content"></amp-img>
/* amp-img タグのスタイル */.i-amphtml-layout-size-defined{overflow:hidden!important;}/* i-amphtml-sizer タグのスタイル */element.style{padding-top:66.6667%;}.i-amphtml-sizer{display:block!important;}

layout="responsiveの場合、amp-img の直下に img タグに加えて i-amphtml-sizer タグが挿入されます。
amp-img タグの widthheightに指定した値から、画像のアスペクト比は 1080:720 = 3:2となります。
このアスペクト比を維持した状態で、表示可能な領域内で画像を拡大・縮小させるために、2 / 3 * 100 ≒ 66.6667%;padding-topとして与えています。
i-amphtml-sizer タグによって親要素の amp-img の大きさが確保され、その amp-img の大きさに合わせて img タグが広がることで、画像のアスペクト比を維持したまま画像が拡大・縮小されます。
この方法であれば、IE11 でもレイアウトシフトを防ぐことができます。

layout="flex-item"

フレックスボックスの親要素の直下でフレックスアイテムとして画像を扱いたい場合に使用します。
親要素のスタイルと兄弟要素の数によって画像の大きさが変化します。

flex-item.gif

<amp-imgsrc="/static/samples.jpg"layout="flex-item"alt="sample"></amp-img>

↓ 画像ロード後

<amp-imgsrc="/static/samples.jpg"layout="flex-item"class="i-amphtml-layout-flex-item i-amphtml-layout-size-defined i-amphtml-element i-amphtml-layout"i-amphtml-layout="flex-item"alt="sample"><imgdecoding="async"alt="sample"src="//static/samples.jpg"class="i-amphtml-fill-content i-amphtml-replaced-content"></amp-img>
/* amp-img タグのスタイル */.i-amphtml-layout-flex-item{display:block;position:relative;flex:11auto;}

flex: 1 1 auto;が指定されているため、フレックスボックスの直下に layout="flex-item"の amp-img を隣接して配置して横に並べた場合、同じ幅で並びます。
また、兄弟要素がlayout="flex-item"の要素のみで高さを持たない場合は、親要素のフレックスボックスに高さを明示的に与える必要があります。

layout="intrinsic"

intrinsic.gif

画像自体の本来のサイズか CSS による制限(max-width など)に達するまで、widthheight属性で指定されたアスペクト比を維持したまま使用可能なスペースに合わせて拡大・縮小します。

<amp-imgsrc="/static/samples.jpg"width="1080"height="720"layout="intrinsic"alt="sample"></amp-img>

↓ 画像ロード後

<amp-imgsrc="/static/samples.jpg"width="1080"height="720"layout="intrinsic"alt="sample"class="i-amphtml-element i-amphtml-layout-intrinsic i-amphtml-layout-size-defined i-amphtml-layout"i-amphtml-layout="intrinsic"style="--loader-delay-offset:241ms !important;"><i-amphtml-sizerclass="i-amphtml-sizer"slot="i-amphtml-svc"><imgalt=""role="presentation"aria-hidden="true"class="i-amphtml-intrinsic-sizer"src="data:image/svg+xml;charset=utf-8,<svg height=&quot;720px&quot; width=&quot;1080px&quot; xmlns=&quot;http://www.w3.org/2000/svg&quot; version=&quot;1.1&quot;/>"></i-amphtml-sizer><imgdecoding="async"alt="sample"src="/static/samples.jpg"class="i-amphtml-fill-content i-amphtml-replaced-content"></amp-img>
/* amp-img タグのスタイル */.i-amphtml-layout-size-defined{overflow:hidden!important;}.i-amphtml-layout-intrinsic{display:inline-block;position:relative;max-width:100%;}/* i-amphtml-sizer タグのスタイル */.i-amphtml-layout-intrinsic.i-amphtml-sizer{max-width:100%;}i-amphtml-sizer{display:block!important;}/* i-amphtml-sizer タグ直下の img タグのスタイル */.i-amphtml-intrinsic-sizer{max-width:100%;display:block!important;}

layout="responsive"と同様に amp-img の直下に img タグに加えて i-amphtml-sizer タグが挿入されます。
しかし、layout="intrinsic"の場合は i-amphtml-sizer の直下にさらにもう一つ img タグが挿入されます。
layout="responsive"では、空の i-amphtml-sizer タグに指定された paddingが画像の表示領域を確保していたのに対し、 layout="intrinsic"では i-amphtml-sizer タグの直下の img タグによって表示される透明な svg 画像によって画像の表示領域を確保します。
svg 画像のサイズは amp-img に指定した widthheight属性によって決まり、img タグであるため画像自体の大きさより大きくなることはありません。

また、i-amphtml-sizer タグ内の img タグには、role="presentation"aria-hidden="true"を指定することで、見た目を変えるために使用されている重要な意味を持たない要素であることを明示してあり、アクセシビリティにも考慮されていることがわかります。

layout="nodisplay"

要素は非表示になり、スペースを占有しません。

<amp-imglayout="nodisplay"src="/static/sample.jpg"width="1080"height="720"layout="nodisplay"></amp-img>

↓ 画像ロード後

<amp-imglayout="nodisplay"src="/static/sample.jpg"width="1080"height="720"class="i-amphtml-layout-nodisplay i-amphtml-element"hidden=""i-amphtml-layout="nodisplay"></amp-img>
/* amp-img タグのスタイル */[hidden]{display:none!important;}

AMP コンポーネント共通の hidden属性が付与され、display: none;が適用されます。

まとめ

amp-img を使用しない場合でもwidthheightdecodingといった属性を適切に指定するなど、パフォーマンス改善のために画像周りで工夫できることが多くあることがわかりました。
amp-img は遅延ロードやフォールバックといった機能を提供してくれるので、改めて便利だと感じました。
完全に AMP 対応したサイトではないとしても画像を便利に扱うために amp-img を使用するのも一つの選択肢だと思いました。
画像の扱いは web サイトのパフォーマンスを低下させる大きな要因になり得るので、先人の知恵を借りながらベストな実装を追いかけていきたいですね。


  1. IEは非対応: https://caniuse.com/mdn-html_elements_img_decoding 

  2. layoutの値により、width / heightが必須かどうかは異なります。 

[CSS] flex align-itemsの混合の方法

$
0
0

CSSで要素の縦並びを中央揃えにしたり上揃えにしたりしたくなる時ありますよね?

単に中央揃えにしたかったら親要素を次の通りにすればいいだけです。

.parent{display:flex;align-items:center;}

でも、ある子要素だけ中央揃えでなくベースラインにしたい場合はどうすればいいでしょうか?

調べたところ、どうやらalign-selfをその子要素に設定すればいいようでした。

.parent{display:flex;align-items:center;}.top{align-self:baseline;}

コードの全体はCodePenに上げました。
https://codepen.io/kter/pen/jOqJEGO

【作ってみた】js不使用。CSSだけでマウスホバーで動く自動ドア作った。

$
0
0

どうも7noteです。電車に乗っていてふと突然、「そうだ自動ドア作ろう」って思ったので作ってみた。

完成予定イメージ

閉じてるとき↓
close.png

開いたとき↓
open.png

ソース

予想していたよりも短くコンパクトに書けました。

index.html
<divclass="doors"><divclass="door left"></div><divclass="door right"></div></div>
style.css
.doors{width:200px;/* ドア2枚分の横幅 */height:300px;/* ドアの高さ */overflow:hidden;/* 空いたとき、ドアを消す為のもの。 */border:solid2px#000;/* ドア全体の枠線 */display:flex;/* 2枚のドアを横並びにする */}.door{background:linear-gradient(-135deg,#AAD5EE50%,#FFF50%,#FFF60%,#AAD5EE60%);/* グラデーションを使ってガラスっぽさを表現 */width:100px;/* ドア1枚分の横幅 */height:300px;/* ドアの高さ */border:solid1px#EEE;/* ドアの枠線 */box-sizing:bordre-box;/* 余白の計算を簡単にするため */transition:all.5s;/* ドアがゆっくり開く */}.doors:hover.left{transform:translateX(-97%);/* マウスホバー時に、左に動く */}.doors:hover.right{transform:translateX(97%);>/* マウスホバー時に、右に動く */}

movie.gif

解説

とっても簡単にそれっぽく見せることができました。
実際にガラスのように透かして見せる場合はbackground#AAD5EEを全てrgba(0,153,255,0.4)くらいに変えてください。
時間帯によって、ガラスの色合いが変わるとかになったら綺麗かも。そうなるとCSSだけじゃ厳しいか・・・

おそまつ!

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


【Rails6.0】突然CSSが読み込まれなくなった、、【怪奇現象?】

$
0
0

現在個人開発でRailsアプリを作っているのですが、正常に動いていたRailsアプリのCSSが突然読み込まれなくなり(画像ファイルも)無駄に時間を食ってしまいました。
結局はっきりとした原因はわかりませんが、解決するまでの過程をここに書いていこうと思います。

開発環境

  • windows10 Pro
  • Rails: 6.0.3.2
  • ruby: 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
  • Docker for windows
  • MySQL 5.7
  • nginx:1.15.8

エラーが発生した経緯

rspecのシステムスペックでテストを書いて実行、失敗を10回ほど繰り返してlocalhost(root_path)にアクセスしたら
CSSが反映されなくなっていた。
そのときのConsoleのエラー内容↓

Failed to load resource: the server responded with a status of 500 (Internal Server Error) 

このエラー自体はよく見るやつで、タイトル通りCSSファイルが読み込まれていないというものでした。

解決手順(?)

この解決策が正しいのか正直微妙ですが、治るまでの経緯をここに書かせて頂きます。
結論から言いますと、nignx.confの内容を適当に書き換えて、dockerコンテナをビルドし直して起動しなおしてエラーを起こしてもう一度ビルドし直してコンテナ起動したら治ったという感じです。普通に再ビルドしただけでは治りませんでした。これのせいで時間がかかりましたね、、たまたまエラー起こせたんで治せましたが、、
これだとわかる人にしかわからないでの以下で詳しく説明します。

1.nginx.confの内容を書き換える

私の開発環境ではなるべく本番環境に近づけるためにWEBサーバーとしてnginxコンテナを起動させています。
そのnginx.confはその設定ファイルです↓

# プロキシ先の指定
# Nginxが受け取ったリクエストをバックエンドのpumaに送信
upstreamwebapp {
  # ソケット通信したいのでpuma.sockを指定
serverunix:///webapp/tmp/sockets/puma.sock;
}

server {
  listen80;
  # ドメインもしくはIPを指定
server_namewebapp ;

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;

  # ドキュメントルートの指定
root /webapp/public;

  client_max_body_size100m;
  error_page404             /404.html;
  error_page505502503504 /500.html;
  try_files  $uri/index.html $uri @webapp;
  keepalive_timeout5;

  # リバースプロキシ関連の設定
location @webapp {
    proxy_set_headerX-Real-IP $remote_addr;
    proxy_set_headerX-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_headerHost $http_host;
    proxy_passhttp://webapp;
  }
}

この設定ファイルのproxy_passを適当に書き換えてわざとエラーをおこします。(場所はどこでもいいかも)

2.dockerを再ビルドして起動する。

$ docker-compose down
$ docker-compose up -d --build

-dオプションはバックグランドで実行してくれます。
--buildオプションをつけるとビルドから起動まで一気にやってくれます。

そうすると、

$ docker-compose ps
    Name                  Command               State           Ports
----------------------------------------------------------------------------
webapp_app_1   bundle exec puma -C config ...   Up
webapp_db_1    docker-entrypoint.sh mysqld      Up       3306/tcp, 33060/tcp
webapp_web_1   /bin/sh -c /usr/sbin/nginx ...   Exit 1

エラーが起きて webapp_web_1コンテナがExitするはずです。(コンテナ名は、docker-compose.ymlの設定で変わるので各自置き換えてください。)

3.書き換えたnginx.confを元に戻して再ビルド

ここで適当に書き換えてわざとエラーを起こしたnginx.confのファイルを元に戻します。
そして2を再び実行します。
そしたらなぜか反映されるようになりました!嬉しい!!

最後まで読んでいただきありがとうございます!

正直今回の方法がどういうロジックで治ったのか?そもそも正しいのか?というのはわかりません。もし、わかるかたがいましたらコメントいただけると幸いです。

とりあえず、これをやったら治ったというのは事実です。production環境でプリコンパイル時にCSS読み込みがうまくいかないとかならまだわかるんですが、今回は突然のエラーだったので治すのに時間がかかってしまいました。同じエラーに遭遇している方に、こちらが役に立てばうれしいです!

styled-componentsでレスポンシブを楽に書く

$
0
0

はじめに

今回はstyled-componentsを使ってレスポンシブデザインをできるだけ楽にする方法を紹介します。

他のstyled-componentsの記事はこちら
* styled-componentsを使ってみる
* styled-componentsでJavascriptの値を使う
* styled-componentsのThemeを使ってみる

実際に描いてみる

今回のは一回書いてしまえばつかいまわせるので簡単に書きます。

src直下にmedia.tsを作成し、以下のコードを書きます。Javascriptで書く場合はtypeの部分は全部消します。

src/media.ts
import{css,CSSObject,FlattenSimpleInterpolation,SimpleInterpolation,}from'styled-components';exportconstsp=(first:CSSObject|TemplateStringsArray,...interpolations:SimpleInterpolation[]):FlattenSimpleInterpolation=>css`
    @media (max-width: 560px) {
        ${css(first,...interpolations)}
    }
`;exportconsttab=(first:CSSObject|TemplateStringsArray,...interpolations:SimpleInterpolation[]):FlattenSimpleInterpolation=>css`
    @media (min-width: 561px) and (max-width: 1024px) {
        ${css(first,...interpolations)}
    }
`;exportconstpc=(first:CSSObject|TemplateStringsArray,...interpolations:SimpleInterpolation[]):FlattenSimpleInterpolation=>css`
    @media (min-width: 1025px) {
        ${css(first,...interpolations)}
    }
`;

styled-componentsからインポートしたcssは、関数みたいにも使えます。sp(スマートフォン)、tab(タブレット)、pc(パソコン)という関数を作って、それぞれのサイズでスタイルを当てたい時に呼び出して使います。

引数のタイプはVSCodeの型推論と同じになるようにしただけです。

次にApp.tsxで以下のコードを書いて、使ってみましょう。

src/App.tsx
importReactfrom'react';importstyledfrom'styled-components';import{pc,sp,tab}from'./media';exportconstApp=()=><Box>レスポンシブ</Box>;
constBox=styled.div`
    background-color: red;
    ${sp`
        width: 20px;
        height: 20px;
    `}${tab`
        width: 50px;
        height: 50px;
    `}${pc`
        width: 100px;
        height: 100px;
    `}
`;

ブラウザで確認するとそれぞれのサイズでちゃんと赤い正方形のサイズが変わると思います。
ブレイクポイントなど自由に変えて使ってみてください。

終わりに

ここまで読んで頂きありがとうございます!現在、PHP(Laravel)を中心に勉強しているのでそちらの方の記事を多く投稿していくと思います。感想やリクエストなどどんどん送ってくれると嬉しいです!

参考記事

styled-componentsを使ってみる

$
0
0

はじめに

今回はstyled-componentsの簡単な使い方をやります。

他のstyled-componentsの記事
* styled-componentsでJavascriptの値を使う
* styled-componentsのThemeを使ってみる
* styled-componentsでレスポンシブを楽に書く

styled-componentsとは?

styled-componentsはReactにおけるCSSの当て方の一つで、Reactのコンポーネントのようにjsの値を渡したりでき、コンポーネントのようにスコープが作られるため、使いやすいです。

インストール

Reactの環境ができている方は下のコマンドはスルーしてください。
できていない方は以下のコマンドを打つか、記事を見ながら作ってみてください。
typescriptを使わない場合は下のコマンドの--typescriptは必要ありません。

ターミナル
npx create-react-app --typescript [アプリ名]

webpackでReact+Typescriptの環境構築をする

VSCodeで開き、ターミナルで以下のコマンドを打ちます。Typescriptを使わない場合は@types/styled-componentsは必要ありません。

VSCodeのターミナル
//npm
npm install --save styled-components
npm install --save-dev @types/styled-components

//yarn
yarn add styled-components
yarn add -D @types/styled-components

準備完了!

実際に使ってみる

早速使ってみましょう!

普通にスタイルを当てる

まずはApp.tsxに以下のコードを書いてブラウザで見てみましょう。

src/App.tsx
importReactfrom'react';exportconstApp=()=>{return<h1>HelloWorld!</h1>;
};

ちなみにindex.tsxは以下のようにしています。

src/index.tsx
importReactfrom'react';importReactDOMfrom'react-dom';import{App}from'./App';ReactDOM.render(<App/>,document.getElementById('app'));

ただの黒いHello World!が表示されるはずです。

次にstyled-componentsを使って、スタイルを当ててみましょう。
以下のような感じで使います。

VSCodeの拡張機能のvscode-styled-componentsを入れるとシンタックスハイライトが効いてみやすくなります。

const[コンポーネントとして使う名前]=styled.[タグ名]`
    //style
`;

App.tsxにstyled-componentsをインポートして、h1にスタイルを当てています。

src/App.tsx
importReactfrom'react';importstyledfrom'styled-components'exportconstApp=()=>{return<Title>HelloWorld!</Title>;
};constTitle=styled.h1`
    color: red;
`;

今度は赤く表示されるはずです。

補足:下のコードように連想配列で書く書き方もあるみたいです。詳しくはドキュメント

constBox=styled.div({background:'palevioletred',height:'50px',width:'50px'});

コンポーネント内の要素にスタイルを当てる

App.tsxを以下のように書き換えてみましょう。

src/App.tsx
importReactfrom'react';importstyledfrom'styled-components';exportconstApp=()=>{return(<TitleWrapper><h1>HelloWorld!</h1>
</TitleWrapper>
);};constTitleWrapper=styled.div`
    text-align: center;
    h1 {
        color: red;
    }
`;

中心に赤くHello World!が表示されるはずです。
上のようにある要素の中の要素にスタイルを当てるといった使い方もできます。

擬似要素を使う

App.tsxを以下のように書き換えてみましょう。

src/App.tsx
importReactfrom'react';importstyledfrom'styled-components';exportconstApp=()=>{return(<TitleWrapper><h1>HelloWorld!</h1>
<Button>Hover</Button>
</TitleWrapper>
);};constTitleWrapper=styled.div`
    text-align: center;
    h1 {
        color: red;
    }
`;constButton=styled.button`
    color: white;
    background-color: blue;
    &:hover {
        background-color: skyblue;
    }
`;

先ほどに加えて、hoverで水色になるボタンが表示されます(hover前は青)。

&の後に擬似要素を書くことで使えます。

コンポーネントにスタイルを当てる

App.tsxを以下のように書き換えてみましょう。

src/App.tsx
importReactfrom'react';importstyledfrom'styled-components';exportconstApp=()=>{return(<TitleWrapper><h1>HelloWorld!</h1>
<Button>Hover</Button>
<StyledButton>Hover</StyledButton>
</TitleWrapper>
);};constTitleWrapper=styled.div`
    text-align: center;
    h1 {
        color: red;
    }
`;constButton=styled.button`
    color: white;
    background-color: blue;
    &:hover {
        background-color: skyblue;
    }
`;constStyledButton=styled(Button)`
    color: black;
    background-color: white;
`;

上では色だけを変えたボタンを新しく作っています。このように、作ったコンポーネントに上書きする形でスタイルを当てる事ができます。
MaterialUIなどにも使う事ができて便利です。

ここまで読んでいただきありがとうございます!少しでもお役に立てれば幸いです!

参考記事

styled-componentsドキュメント

styled-componentsでJavascriptの値を使う

$
0
0

はじめに

一応、下の記事の続きとして書いているのでインストールなどはお手数ですが下の記事をご覧ください。

他のstyled-componentsの記事
* styled-componentsのThemeを使ってみる
* styled-componentsでレスポンシブを楽に書く

今回はstyled-componentsでJavascriptの値を使う方法を試していきます。

実際にやってみる

連想配列で定義した値を使う

まず、srcディレクトリ直下にstyle.tsファイルを作り、以下のコードを書きます。

src/style.ts
exportconstCOLOR={RED:'#FF0000',ORANGE:'#FFA500',YELLOW:'#FFFF00',GREENYELLOW:'#ADFF2F',GREEN:'#008000',BLUE:'#0000FF',SKYBLUE:'#87CEEB',PURPLE:'#800080',PINK:'#FFC0CB',BROWN:'#A52A2A',WHITE:'#FFFFFF',GRAY:'#808080',BLACK:'#000000',};

上のコードを見ると、色の名前とカラーコードの連想配列になっています。

App.tsxに以下のようなコードを書いてみましょう。App.tsxはsrc直下にあり、index.tsxにインポートする感じで書いています。

src/App.tsx
importReactfrom'react';importstyledfrom'styled-components';import{COLOR}from'./style';exportconstApp=()=>{return(<TitleWrapper><h1>HelloWorld!</h1>
<Button>Click</Button>
</TitleWrapper>
);};constTitleWrapper=styled.div`
    text-align: center;
    h1 {
        color: ${COLOR.RED};
    }
`;constButton=styled.button`
    color: ${COLOR.WHITE};
    background-color: ${COLOR.BLUE};
    &:hover {
        background-color: ${COLOR.SKYBLUE};
    }
`;

先ほど作ったstyle.tsをインポートしてスタイルに使っています。このように、色や大きさの値をどこかのファイルにまとめて、インポートして使う感じにすると共同開発でもわかりやすくなります。

propsを渡して、その値を使う(例1)

App.tsxを以下のように書き換えてみましょう。Typescriptを使わない場合は、interfaceやの部分は消しましょう。

src/App.tsx
importReact,{useState}from'react';importstyledfrom'styled-components';exportconstApp=()=>{const[is_red,set_is_red]=useState(true);consthandleClick=()=>{set_is_red(!is_red);};return(<TitleWrapperis_red={is_red}><h1>HelloWorld!</h1>
<ButtononClick={handleClick}>Click</Button>
</TitleWrapper>
);};interfaceITitleWrapper{is_red:boolean;}constTitleWrapper=styled.div<ITitleWrapper>`
    text-align: center;
    h1 {
        color: ${({is_red})=>is_red?'red':'blue'};
    }
`;constButton=styled.button`
    color: white;
    background-color: blue;
    &:hover {
        background-color: skyblue;
    }
`;


※実際はクリックすると赤と青で切り替わります

上から見ていきましょう。まず、is_redという初期値がtrueのstateを作り、is_redはButtonをクリックするたびにtrue<->falseで切り替わる事がわかります。また、TitleWrapperにはis_redを渡している事がわかります。

そして、下の方のTitleWrapperを見てみるとis_redの値が使われています。ここでは三項演算子を使って、h1のテキストの色を変えています。

is_redの状態
true     赤     
false

propsを渡して、その値を使う(例2)

また、下のようにスタイルの連想配列をそのまま渡す方法もあります。

src/App.tsx
importReact,{useState}from'react';importstyledfrom'styled-components';exportconstApp=()=>{const[text_color,set_text_color]=useState({color:'blue'});consthandleClick=()=>{set_text_color({color:'red'});};return(<TitleWrappertext_color={text_color}><h1>HelloWorld!</h1>
<ButtononClick={handleClick}>Click</Button>
</TitleWrapper>
);};interfaceITitleWrapper{text_color:{color:string;};}constTitleWrapper=styled.div<ITitleWrapper>`
    text-align: center;
    h1 {
        ${({text_color})=>text_color};
    }
`;constButton=styled.button`
    color: white;
    background-color: blue;
    &:hover {
        background-color: skyblue;
    }
`;

※この場合はクリックしたら青から赤になり、その後にボタンを押しても色は変わりません

渡された連想配列がそのままスタイルとして適用されています。

うまく説明できたかわかりませんが。styled-componentsでは今回説明したJavascriptの値を使えるという部分が個人的にかなりいいなと思っています。次はthemeについて書きたいと思います。

ここまで読んでいただきありがとうございます!少しでもお役に立てれば幸いです!

参考記事

styled-componentsドキュメント

styled-componentsのThemeを使ってみる

$
0
0

はじめに

今回はstyled-componentsのThemeに焦点を当てていきたいと思います。
themeに関しては実務で使った事がなく、あまり理解できていないところもあるので、詳しい方コメントで教えていただけると幸いです^_^

他のstyled-componentsの記事はこちら

themeとは?

ReduxみたいにProviderで囲ったコンポーネント内のどこからでもアクセスできる値みたいなイメージです。

styled-componentsドキュメント引用↓

// Define our button, but with the use of props.theme this timeconstButton=styled.button`
 color: ${props=>props.theme.fg};
 border: 2px solid ${props=>props.theme.fg};
 background: ${props=>props.theme.bg};
 font-size: 1em;
 margin: 1em;
 padding: 0.25em 1em;
 border-radius: 3px;
`;// Define our `fg` and `bg` on the themeconsttheme={fg:"palevioletred",bg:"white"};// This theme swaps `fg` and `bg`constinvertTheme=({fg,bg})=>({fg:bg,bg:fg});render(<ThemeProvidertheme={theme}><div><Button>DefaultTheme</Button>
<ThemeProvidertheme={invertTheme}><Button>InvertedTheme</Button>
</ThemeProvider>
</div>
</ThemeProvider>
);

themeのメリット

themeというぐらいなので、色を全体的に変えたりなどスタイルの雰囲気をガラッと変えたりするのに使いやすそうです。

実際に使ってみる

ドキュメントの例でも十分ですが、せっかくなので使ってみましょう!
index.tsxにAppProviderコンポーネントを作って、ボタンを押したらthemeが切り替わる感じにします。

AppコンポーネントはThemeProviderで挟んで、themeを渡します。これでAppコンポーネント内ではt hemeが使えます。

src/index.tsx
importReact,{useState}from'react';importReactDOMfrom'react-dom';import{ThemeProvider}from'styled-components';import{App}from'./App';constAppProvider=()=>{const[is_theme_dark,set_is_theme_dark]=useState(false);constdefault_theme={text_color:'black',background_color:'white',}constdark_theme={text_color:'white',background_color:'black'}consttoggle_theme=()=>{set_is_theme_dark(!is_theme_dark);};return(<><buttononClick={toggle_theme}>Change!</button>
<ThemeProvidertheme={is_theme_dark?dark_theme:default_theme}><App/></ThemeProvider>
</>
);};ReactDOM.render(<AppProvider/>,document.getElementById('app'));

次にAppコンポーネントことApp.tsxに以下のコードを書きます。

src/App.tsx
importReact,{useContext}from'react';importstyled,{ThemeContext}from'styled-components';exportconstApp=()=>{consttheme=useContext(ThemeContext);return(<TitleWrapper><h1>HelloWorld!</h1>
<Button>NoEvent</Button>
</TitleWrapper>
);};constTitleWrapper=styled.div`
    width: 100vw;
    height: 100vh;
    background-color: ${(props)=>props.theme.background_color};
    text-align: center;
    h1 {
        color: ${(props)=>props.theme.text_color};
    }
`;constButton=styled.button`
    color: ${(props)=>props.theme.text_color};
    background-color: ${(props)=>props.theme.background_color};
`;

themeはhooksのuseContextにstyled-componentsからインポートしたThemeContextを渡してあげるとindex.tsxで定義したthemeの値が入ります。そしてテーマの値をスタイルに使っています。

ブラウザを見てみると下の画像のようにdefault_themeが表示されると思います。

左上のボタンを押すとdark_themeに変わります。

使ってみた感想

今回は簡単な物を作ったのであまり恩賜を受けられませんでしたが、グローバルステートと組み合わせて、サイト全体のテーマを変えたりするのに使えそうな感じがしました。

ここまで読んでいただきありがとうございます!今後もいろいろな記事を書いていきたいと思っているので感想や要望などいただけたら、モチベーションにもつながります。

参考記事

styled-componentsドキュメント

可変ヘッダーの高さ分だけコンテンツを下げる

$
0
0

headerを固定したら下の要素と重なる時の対処法(headerの高さが可変)

がうがうです。
headerを固定した時に下に続く要素が重なる時の対処法です。
試行錯誤して3種類試したので覚え書きです。

先日マークアップの練習としてそれっぽいページを作っていた時に
ヘッダーを固定すると、

1.ヘッダーと下に続く要素が重なる
2.ページ内リンクした時に見出しの位置がズレる

以上2点の問題が発生したので、色々調べてみました。

コードサンプル


See the Pen
qiita_css_position-sticky/sample-failure
by がうがう (@gawgaw-2020)
on CodePen.



今回はヘッダーの高さがPC表示とスマホ表示で可変になっています。

結論 色々試した結果「position: sticky」が便利だった

様々なアプローチがあると思いますが、marginで高さをとったり、JavaScriptで挑戦してみましたが、
最終的に「position: sticky」が一番シンプルに記述できたので記事にしてみました。

デモはこちら

position: stickyで解決

https://gawgaw-2020.github.io/qiita_css_position-sticky/sample-sticky/

CSSのみ。marginで解決

https://gawgaw-2020.github.io/qiita_css_position-sticky/sample-margin/index.html

JavaScriptで解決

https://gawgaw-2020.github.io/qiita_css_position-sticky/sample-js/index.html

GitHubはこちら

https://github.com/gawgaw-2020/qiita_css_position-sticky

CSSのみ。position: stickyで解決

ヘッダータグのposition: fixedposition: stickyに変更

header{width:100%;background-color:rgba(0,0,0,.7);height:90px;/* ヘッダーを固定 *//* position: sticky;に変更 */position:sticky;top:0;z-index:9999;}

position: sticky
高さが保たれる
指定した位置にくっつく
といった特徴があるため、ヘッダーの高さが可変でも下に続く要素が隙間なく続いてくれました。

See the Pen qiita_css_position-sticky/sample-sticky by がうがう (@gawgaw-2020) on CodePen.

CSSのみ。marginで解決

参考にしたサイトでもこの方法で解決が多かったです。

1.後に続く要素のmargin-topをヘッダーの高さ分とる

.top-image{height:800px;background-image:url(../img/top-image.jpeg);background-size:cover;background-position:center;/* ヘッダーの高さ分余白をとる */margin-top:90px;}

2.スマホ時にヘッダーの高さが変わるので、その分margin-topも修正

@mediascreenand(max-width:768px){.top-image{margin-top:40px;}}

この方法の場合、ページによってヘッダーの高さが違う場合などに記述が増えたり、管理が大変だなと感じました。

See the Pen qiita_css_position-sticky/sample-margin by がうがう (@gawgaw-2020) on CodePen.

JavaScriptで解決(未解決?)

最近JavaScriptの勉強を始めたので、実は最初にこちらを試しました。
ヘッダーの高さが可変なので「読み込み時にヘッダーの高さを取得して、その分コンテンツを下げよう」というのが魂胆です。

// ヘッダーの高さを取得constheight=document.getElementById('header').clientHeight;// 高さ文のマージンを適用する要素を取得consttopImage=document.getElementById('top-image');// ページ読み込み時にスタイルを追加window.addEventListener('load',()=>{topImage.style.marginTop=height+'px';});

今回はヘッダーの高さが可変のため、
最初に読み込んだ時と、画面幅が変わった場合に明らかにおかしい隙間が発生してしまいます。
スクリーンショット 2020-09-26 12.44.25.png

See the Pen VwaRzby by がうがう (@gawgaw-2020) on CodePen.

resizeイベントと時間差での処理を使って実装でもいいかもしれないと書いていて思いました。

ページ内リンクした時に見出しの位置を合わせる

こちらに関しては、今回はリンク先に「anchor」クラスを追加して対応しました。

<sectionid="philosophy"class="philosophy anchor"><h2>企業理念</h2></section><sectionid="service"class="service anchor"><h2>事業紹介</h2></section><sectionid="contact"class="contact anchor"><h2>お問い合わせ</h2></section>
/* 数値は調整可能 */.anchor{padding-top:120px;margin-top:-120px;}

クラスつける前
スクリーンショット 2020-09-26 12.16.53.png

クラス追加後
スクリーンショット 2020-09-26 12.17.12.png

調整できました。
全てのリンク先にクラスをつけないといけないので、少し面倒臭いなぁと感じてしまうので
JavaScriptなどで調整する方法も調べてみたいと思います。

最後に

「header 固定? fixed & top して padding-top か margin-top して z-index でしょ」から
「他に方法ないかなぁ」と考えることができたので良かったと感じました!!

参考サイト

positionプロパティを身に着けよう!stickyの仕様と使い方を解説!

[CSS] スクロールバーは表示されるが親要素が拡大されてスクロールが機能しない

$
0
0

背景

flex の要素にスクロールバーを追加するため、overflow-y: scrollを追加すると、スクロールバーは表示されるがスクロールしてくれない。

heightを指定すれば解決するが、flex 要素なのでやりたくない。

理想

Screenshot from 2020-09-26 04-40-08.png

現実

Screenshot from 2020-09-26 04-39-47.png

結論

スクロールバーを追加したい要素の親要素を overflow: hiddenとしなければならない。

ソースコード

https://codepen.io/buyoh/pen/vYGPgjx

<divclass="col"style="width: 320px; height: 240px;"><divclass="flex">
    foo
  </div><divclass="flex row"style="overflow-y: hidden;"><divclass="flex scroll"><divid="loongitem"></div></div><divclass="flex">
      bar
    </div></div></div>
body{font-family:monospace;}div{margin:1px;padding:1px;border:1pxsolidred;}.col{display:flex;flex-direction:column;}.scroll{overflow-y:scroll;}.row{display:flex;flex-direction:row;}.flex{flex:11auto;}#loongitem{width:40px;height:800px;background-color:#7cf;}

コメント

何が起きているのか、推測してみました。
デフォルトのvisibleの場合。

  • overflow:scrollの付いた flex 子要素に、縦に長い要素をレイアウトする
  • flex 親要素は、overflow:visibleなので、子要素を全て描画する
  • flex 親要素には高さ指定がされていないので、flex の計算値を無視して(?)子要素が全て描画されるような高さに調整する(?)
  • 子要素の高さは、親要素の高さに追従する
  • びよーん

hiddenの場合。

  • overflow:scrollの付いた flex 子要素に、縦に長い要素をレンダリングする
  • flex 親要素は、overflow:hiddenなので、子要素を全て描画しない
  • 全て描画する必要がないので、親要素の高さは子要素の高さに依存しなくなる
  • 親要素の高さが依存するのは flex の計算値のみ
  • 親は枠からはみ出ない

確かに、一般には要素の高さは親要素では無く子要素に依存しますよね。

依存が逆転するようなケースの場合、子要素の大きさの依存を明示的に断ち切る必要があって、それが今回の overflow:hidden では?


画像高さをキープしたまま画面の幅いっぱいに背景画像を表示させる方法

$
0
0

どうも7noteです。画面幅いっぱいに背景画像を表示したい時の方法を紹介。

また、1920pxくらいある大きな画面で見たときにも崩れにくい方法も解説します。

画面幅いっぱいに画像を出すなら、background-size: cover;

.bg{background-image:url(bg.jpg);background-size:cover;/* 要素いっぱいに */background-position:centercenter;}

だけど横幅の短い画像だと思ったところが表示されないことも。。。

下の例だと崖の部分が映らなくなってしまう場合があります。

なので元の画像を加工して、横幅を1920px以上の画像にします。
そうすることで高さはそのまま、横幅が変わっても幅いっぱいに画像が表示されます。

haba2-(2).gif

これで横幅が変わっても拡大縮小されにくくなりました。

1920pxにしたのは、一般的なディスプレイがおおきいもので1920pxが多いからです。
画像の高さは、実際に表示される高さと同じ

まとめ

オシャレなサイトでよく幅いっぱいに画像を表示するデザインを見かけるので、参考にして入れてみてください。
比較的簡単でオシャレになるので、background-size: cover;は重宝してます。

おそまつ!

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

Tsハロトレ28日目

$
0
0

本日の概要

1.課題サイト作成
2.アップロード(確認)
3.ワイヤーフレーム(書き出し)・・・PDF、PNG、JPEG、SVG

CSS

URLについて

 https://URL(URI)/(「index.html」)
GoogleのSEOのために、「 URL/ 」で終わりたい。
(「index.html」)は、自動的にあるものとして判断されます。

contact.htmlなどは、Google検索で損になります。

全てindex.htmlフォルダ名に工夫することが大事です。

index.png

XFREEやStarserverFreeはWordPress使い始めてからでよいので、
Myサイトは、ホームページ領域を忍者ツールズに載せればよいです。

ホテルの法則

玄関のindex.htmlがないと、全ての情報が盗まれてしまいます。
index3.png

OOCSS

スペースでclassを並列するような書き方をOOCSSと呼びます。
oocss2.png

inherit

inherit.png

rem・em

fzfirst2.png

Google fonts

Noto Sans ≒ 源の角ゴシック
Noto Sans以外のUフォントやメイリオを使うと見栄えが悪くなります。
それに加えて、paddingなどをディセンダのせいで汚くなってしまいます。

Web Fonts(Google API)

font-familyの昔の書き方

font-familyは、使われていない書体から書いていきます。
Mac、Win、Linux、汎用の順
今は、Noto Sansだけ書いていればよいです。
それの方がコンピュータにどのフォントを選ぶか
という余計なコストをかけなくて済みます。

インラインレベル要素のクラス名

①ブロックレベル要素のクラス名の場合
 .xxx
②インラインレベル要素の場合
 a.current インラインレベル要素名.クラス名

CSSシグネチャー

シグネチャー2.png

Macサーバー

Macのサーバーはセキュリティー的にCyberduckを使えばよいです。
授業では、WinSCPを使います。

無料サーバーではFTPを使うこと

FTPを使う事2.png

新しいサイトをアップロードしたいとき

別のアカウントを忍者ツールズで作って行います。

illustrator

ワイヤーフレーム

wireframe.ai
wireframe.pdf
wireframe.gif
wireframe.png
wireframe.jpeg

スマホとPC用のサイトのワイヤーフレームをPDF用の保存

ファイル>別名で保存
pdfで保存2.png

スマホとPC用のサイトのワイヤーフレームをjpegやpng用での保存

ファイル>Web用に保存
Web用2.png

日本のサイトの四季を作ってみる

nav_border2.png

height,padding,border-bottom,box-sizing:border-box;を使って作ってみましょう。

 border-boxは、paddingborderを高さや幅に含めます。
スクリーンショット 2020-09-27 12.05.58.png

指にあるスマホを切り抜きたい場合

takkakei2.png

alt+クリック2.png

切り抜かれた後2.png

ドロップダウンリストの実装方法

$
0
0

ドロップダウンリストの実装方法

ドロップダウンリストの実装をJQueryで簡単に行うことができるのですが、
今回は泥臭い方法で、実装していきます。(全て0から実装しました笑)
ほぼCssメインといっても、過言ではないのですが、
JQueyとCssで実装する2パターンを紹介させて頂きます。

index.html
<script>//ここからは、JQuery!$(function(){//nav ul liをマウスでホバーさせるとnav ul ul が出現する。$("nav ul li").mouseenter(function(){//nav ul li(this)の兄弟要素にnav ul ulを含んでいるのかを調査する。$(this).siblings().find("nav ul ul");//nav ul liの子要素であるnav ul ulをdisplay:blockで目に見えるようにする。$(this).children().slideDown(150);});//body内をクリックしたら、nav ul ulをdisplay:noneにして表示させないようにする。$("body").click(function(){$('nav ul ul').slideUp(150);});});</script><divid="nav"><ul><liclass ="first"><ahref="./index.html">トップページ<br>HOME</a></li><liclass="clinic"><ahref="#clinic">医院紹介<br>CLINIC</a><ul><li><ahref="#">新宿</a></li><li><ahref="#">渋谷</a></li><li><ahref="#">赤羽</a></li></ul></li><li><ahref="#service">診察案内<br>SERVICE</a></li><li><ahref="#staff">院長/スタッフ紹介<br>STAFF</a><ul><li><ahref="#">院長紹介</a></li><liclass = "parent"><ahref="#">スタッフ紹介</a><ulclass ="children"><li><ahref="#">赤羽茜</a></li><li><ahref="#">宇田川茂良</a></li><li><ahref="#">渋谷真知子</a></li></ul></li><liclass = "parent"><ahref="#">中途採用</a><ulclass ="children"><li><ahref="#">正社員</a></li><li><ahref="#">受付アルバイト</a></li><li><ahref="#">契約社員</a></li></ul></li></ul></li><liclass ="last"><ahref="#access">アクセス/Q&A<br>Access</a><ul><li><ahref="#">アクセス</a></li><li><ahref="#">営業時間</a></li></ul></li></ul></div>
style.css
navul{display:flex;width:1050px;margin:0auto;}navulul{position:absolute;width:100%;top:100%;left:0;display:none;}navululli{width:100%;background-color:navy;border-bottom:1pxsolid#fff;right:0px;width:190px;z-index:999;position:relative;}navul>li{justify-content:center;background-color:#6CC6C4;width:20%;padding:10px;text-align:center;border-right:1pxsolidwhite;position:relative;}navullia{font-size:0.85em;}navullia{color:white;text-decoration:none;}navul>ul>li{background-color:#6CC6C4;width:200px;display:block;padding:10px;text-align:center;border-right:1pxsolidwhite;}li.parent{position:relative;}ul.children{left:100.8%;top:0;position:absolute;display:none;}/*li.parentをhoverすると、子要素のul.childrenが、出現する!*/li.parent:hoverul.children{display:block;opacity:0.87;}

完成イメージ図
https://www.nxworld.net/wp-content/uploads/2016/06/css-simple-hoverable-dropdown.png

色や幅に関しては、お好みで調整してみてくださいね!では、アディオス!

Django Sprint #4 トップページの作成 (Docker Toolbox向け)

$
0
0

この記事はDocker Toolbox (≒ Windows 10 Home) ユーザー向けです。Docker (Mac OS, Windows 10 Professional / Enterprise) ユーザーの方はDjango Sprint #4 トップページの作成へ。

目次

  1. HTML, CSS, JavaScript
  2. トップページの作成の準備
  3. トップページの作成
  4. コードの再利用

HTML, CSS, JavaScript

ここからは、フロントエンドの内容にも触れながら進めていきます。実際に目に見える変化が大きくなるので、作っていく感覚を今まで以上に得られると思います。

テンプレートはブラウザとビューの架け橋になるとDjango Sprint #3 ユーザーモデルのカスタマイズ (Docker Toolbox向け)で述べましたが、不正確を承知で端的に言うと、テンプレートはHTMLファイルそのものと考えてもらって構いません。ではHTMLファイルとCSSとはどのようなものでしょうか?

HTML

HTMLとはブラウザに表示するページの「骨格」を規定するものです。タグと呼ばれるものを使って、構造と意味を与えます。試しにブラウザ上で好きなサイトにアクセスし、適当な場所で右クリック→ページのソースを表示(ブラウザにより多少表記が異なる)をクリックしてみましょう。それで表示されるのがHTMLファイルの中身です。インターネット上のほぼあらゆるページはHTMLによって記述されていると言っても過言ではありません。

CSS

HTMLだけでは見た目がかなり簡素なものとなってしまいます。(授業のサイトとかでたまに見る?)CSSはHTMLの見た目を整える役割があります。HTMLを骨と例えるなら、CSSは筋肉です。具体的には、ボタンなどのオブジェクトとその配置やフォントなどを規定しています。

JavaScript

JavaScriptはページの見た目を動的に変えるときに使います。例えば、ハンバーガーメニュー、スライドショー、ボタンをクリックしたときのエフェクトなどに使います。

その他の知識

レスポンシブデザイン

最近はスマートフォンやタブレットなど、通常のパソコンだけでなくあらゆるデバイスを想定しなければなりません。デバイスの画面幅によってスタイルを変えるようなデザインをレスポンシブデザインと言います。これをスクラッチでCSSで記述するのはかなりの量のコードを書かなければなりません。そこで登場するのが、CSSフレームワークです。

CSSフレームワーク

CSSフレームワークを使うことで、一からCSSファイルを書くことなく、スタイルを実装することができます。用意されたパーツを組み立てていくイメージです。多くのモダンなフレームワークではレスポンシブデザインをサポートしています。

代表的なものを上に挙げました。

本チュートリアルではBulmaを使うことにします。具体的な使い方に関しては、これから実際に使っていく中で理解できると思います。

トップページの作成の準備

さて、早速トップページを作っていきましょう。データの出し入れがなく、ただ情報が載っているだけのページを静的なページ(static pages)と呼ぶことがあります。静的なページの作り方を学ぶ前に、いくつか準備をしましょう。

template用ディレクトリの作成

templateファイル(HTMLファイル)を置いておくディレクトリを「cms」直下に作成します。

code
├─ cms
│  ├─ migrations
│  ├─ templates
│  │  └─ cms
...

「templates」と「cms」はディレクトリです。このような二重の構造をとる理由はアプリケーションの再利用を容易にするためです。このcms直下にhtmlファイルを保存していきます。

静的ファイル用ディレクトリの作成

静的ファイルとは画像ファイルやCSSファイルのことです。本チュートリアルではフレームワークを利用し、一切のcssファイルを書きませんが、一応作っておきましょう。

code
├─ cms
│  ├─ migrations
│  ├─ static
│  │  ├─ css
│  │  └─ images
...

アプリへのルーティング

アプリ内のviews.pyを使うためには、アプリ内にもurls.pyを作らなければなりません。cmsディレクトリ直下にurls.pyを作成し、中身を以下のように書き換えます。

/cms/urls.py
fromdjango.urlsimportpathfrom.importviewsapp_name='cms'urlpatterns=[]

これに、元々のconfigディレクトリ内のurls.pyを結びつけます。

/config/urls.py
...fromdjango.contribimportadminfromdjango.urlsimportpath,includeurlpatterns=[path('admin/',admin.site.urls),path('',include('cms.urls')),]

トップページの作成

静的ページの作成フロー

さあ準備が整いました!具体的な手順は以下の通りです。

  1. urls.pyを編集
  2. views.pyを編集
  3. HTMLファイルを編集

URL

例えば、

https://github.co.jp/features

と言うURLを見てみましょう。これは、次のように分けられます。

https + github.co.jp + features

「https」の部分は通信のルール(プロトコル)を表しています。「github.co.jp」の部分はホスト名と言い、サーバー等の「住所」のようなものです。最後に「features」の部分はパス名と言い、「その家の部屋」を表しているイメージです。

ホスト名は別途プロジェクト全体で決めるものなので、urls.pyには基本的にパス名の部分だけを記述すれば大丈夫です。

urls.py

先ほどの設定で「config/urls.py」→「cms/urls.py」の流れを設定できました。なので、基本的にはこれからは「cms/urls.py」をいじることになります。

cms/urls.py
...urlpatterns=[path('',views.TopView.as_view(),name='top'),]

こうすると、パス名がない(トップページはこのような形が多い)ときにviews.pyのTopViewというクラスを参照することになります。オプション引数nameは主にurl関数に渡す際に使います。静的なページではURLが定まっていますが、例えば、ユーザーIDに応じて詳細ページをURLを使って振り分けたいときにurl関数が「気を利かせて」くれるので便利です。

views.py

次に、urls.pyがバトンを渡すTopViewクラスを作成します。

/cms/views.py
fromdjango.views.generic.baseimportTemplateViewclassTopView(TemplateView):template_name='cms/top.html'

ビューは通常関数の形で書かれます。しかし、Djangoでは汎用ビュー(generic view)と言ってよく使うようなビューは全て用意されていて、それを継承するためにクラスを使います。これをクラスベースビューと言います。urls.pyのところで、TopView.as_view()as_viewメソッドを付け加えたのはクラスを無理やり関数の形に変えるためです。汎用ビューについて詳しくは次の #5 で扱うことにします。

この自作の TopView は TemplateView という汎用ビューを継承しています。Template Viewではtemplate_nameという変数にテンプレートファイル(HTMLファイル)へのパスの文字列を代入することで、そのファイルへバトンを渡すことができます。ここでは、cmsディレクトリの中のtop.htmlを探すことになります。

テンプレート

「cms/templates/cms」の直下に、top.htmlを作りましょう。試しに、「Hello, world!!」と表示させましょう。

/cms/templates/cms/top.html
<html><body><p>Hello, world!!</p></body></html>

ここまでこれば、サーバーを立ち上げてブラウザで http://192.168.99.100:8000を確認してみましょう。

>docker-compose up

うまく表示されましたか?

CSSによる装飾

今のままでは簡素すぎるので、フレームワークを使って装飾を加えてみましょう。top.htmlを次のように書き換えて、bulmaを読み込んでみます。

/cms/templates/cms/top.html
<!DOCTYPE html><html><head><metacharset="utf-8"><metaname="viewport"content="width=device-width, initial-scale=1"><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.8.0/css/bulma.min.css"><script defersrc="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script></head><body><pclass="title">Hello, world!!</p></body></html>

<link>タグを用いて、bulmaをインポートしています。さらに、アイコンなどを使用するために font awesomeも併せてインポートしています。

先ほどの<p>タグにclass="title"を付け加えると先ほどの部分がタイトルのように変化します。class="subtitle"にするとどのように変化するでしょうか。各自確認してみましょう。

このようにタグに適当なclass(HTML)を付与することで、装飾します。実際は、

を見てパーツを探してきて、サンプルコードごと付け足してしまえば良いです。

「ほぼ」完成品

実際にはこんな陳腐なページでは嫌なので、次のように書き換えてください。

/cms/templates/cms/top.html
<!DOCTYPE html><html><head><metacharset="utf-8"><metaname="viewport"content="width=device-width, initial-scale=1"><title>Django Sprint</title><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.8.0/css/bulma.min.css"><script defersrc="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script></head><body><!-- NAVIGATION BAR --><header><navclass="navbar"role="navigation"aria-label="main navigation"><divclass="navbar-brand"><!-- LOGO --><aclass="navbar-item"href="/"><imgsrc="https://bulma.io/images/bulma-logo.png"width="112"height="28"></a><!-- HAMBURGER MENU --><arole="button"class="navbar-burger burger"aria-label="menu"aria-expanded="false"data-target="my-menu"><spanaria-hidden="true"></span><spanaria-hidden="true"></span><spanaria-hidden="true"></span></a></div><divclass="navbar-menu"id="my-menu"><divclass="navbar-end"><aclass="navbar-item is-grey"href="#">About</a><divclass="buttons"><aclass="button is-info navbar-item"href="#"><strong>Sign up</strong></a><aclass="button is-light navbar-item"href="#"><strong>Log in</strong></a></div></div></div></nav></header><!-- MESSAGE --><div></div><!-- MAIN --><main><sectionclass="hero is-medium is-info is-bold"><divclass="hero-body"><divclass="container"><h1class="title">Title</h1><h2class="subtitle">Subtitle</h2><ahref="#"><buttonclass="button is-info is-inverted is-outlined"><strong>More Info</strong></button></a></div></div></section><sectionclass="section is-medium"><divclass="container"><divclass="has-text-centered"><h1class="title">Section</h1><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p></div></div></section></main><!-- FOOTER --><footerclass="footer"><divclass="container"><divclass="content has-text-centered">
                2020 <strong>UTokyo Project Sprint</strong></div><divclass="content has-text-centered"><ahref="#"class="has-text-dark">About</a> |
                <ahref="#"class="has-text-dark">Contact</a> |
                <ahref="#"class="has-text-danger">Report an issue</a></div></div></footer><!-- FOR JAVASCRIPT --><script><!--FORHAMBURGERMENU-->for(constburderofdocument.getElementsByClassName('navbar-burger')){constmenuId=burder.dataset.target;constmenu=document.getElementById(menuId);burder.addEventListener('click',e=>{burder.classList.toggle('is-active');menu.classList.toggle('is-active');});}</script></body></html>

コードの再利用

例えば、ナビゲーションバーやフッターなどは全ページで共通しています。ここに変更があったとすると、毎回全てのページについて変更するのは至極困難かつ脆弱です。そこで、「因数分解」のように共通するブロックを切り出します。

base.html

共通因子をbase.htmlというファイルにまとめます。

/cms/templates/cms/base.html
<!DOCTYPE html><html><head><metacharset="utf-8"><metaname="viewport"content="width=device-width, initial-scale=1"><title>{% block title %}{% endblock %}Django Sprint</title><linkrel="stylesheet"href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.8.0/css/bulma.min.css"><script defersrc="https://use.fontawesome.com/releases/v5.3.1/js/all.js"></script></head><body><!-- NAVIGATION BAR --><header><navclass="navbar"role="navigation"aria-label="main navigation"><divclass="navbar-brand"><!-- LOGO --><aclass="navbar-item"href="/"><imgsrc="https://bulma.io/images/bulma-logo.png"width="112"height="28"></a><!-- HAMBURGER MENU --><arole="button"class="navbar-burger burger"aria-label="menu"aria-expanded="false"data-target="my-menu"><spanaria-hidden="true"></span><spanaria-hidden="true"></span><spanaria-hidden="true"></span></a></div><divclass="navbar-menu"id="my-menu"><divclass="navbar-end"><aclass="navbar-item is-grey"href="#">About</a><divclass="buttons"><aclass="button is-info navbar-item"href="#"><strong>Sign up</strong></a><aclass="button is-light navbar-item"href="#"><strong>Log in</strong></a></div></div></div></nav></header><!-- MESSAGE --><div></div><!-- MAIN --><main>
        {% block hero %}{% endblock %}
        {% block tab %}{% endblock %}
        {% block content %}{% endblock %}
    </main><!-- FOOTER --><footerclass="footer"><divclass="container"><divclass="content has-text-centered">
                2020 <strong>UTokyo Project Sprint</strong></div><divclass="content has-text-centered"><ahref="#"class="has-text-dark">About</a> |
                <ahref="#"class="has-text-dark">Contact</a> |
                <ahref="#"class="has-text-danger">Report an issue</a></div></div></footer><!-- FOR JAVASCRIPT --><script><!--FORHAMBURGERMENU-->for(constburderofdocument.getElementsByClassName('navbar-burger')){constmenuId=burder.dataset.target;constmenu=document.getElementById(menuId);burder.addEventListener('click',e=>{burder.classList.toggle('is-active');menu.classList.toggle('is-active');});}{%blockextrajs%}{%endblock%}</script></body></html>

この{% block XXX %}{% endblock %}のところに色々と当てはめていきます。

/cms/templates/cms/top.html
{% extends 'cms/base.html' %}

{% block title %}Home | {% endblock %}

{% block hero %}
<sectionclass="hero is-medium is-info is-bold"><divclass="hero-body"><divclass="container"><h1class="title">Title</h1><h2class="subtitle">Subtitle</h2><ahref="#"><buttonclass="button is-info is-inverted is-outlined"><strong>More Info</strong></button></a></div></div></section>
{% endblock %}

{% block content %}
<sectionclass="section is-medium"><divclass="container"><divclass="has-text-centered"><h1class="title">Section</h1><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p></div></div></section>
{% endblock %}

はじめの {% extends 'cms/base.html' %}によって、base.htmlを読み込んでいます。もう一度ブラウザに戻って確認してみましょう。

静的ファイルの読み込み

現在のナビゲーションメニューのところにはbulmaのロゴが当てはめられていますが、これをカスタマイズしてみましょう。適当な画像ファイル(.svgを推奨)を cms/static/images に配置します。

続いて、base.html にstaticファイルを読み込むことを伝えましょう。

/cms/templates/cms/base.html
{% load static %}

<!DOCTYPE html>
...

最後に画像(今回はacademia.svgという画像を使用した)入れるところをこのように書き換えます。

/cms/templates/cms/base.html
...
<!-- LOGO --><aclass="navbar-item"href="/"><imgsrc="{% static 'images/academia.svg' %}"width="112"height="28"></a>
...

これでうまく表示されたら成功です!

参照

次の記事

Django Sprint #5 汎用ビューとCRUD 前編

前の記事

Django Sprint #3 ユーザーモデルのカスタマイズ (Docker Toolbox向け)

オンラインイナズマ 追加ワーク6日目 模範解答

$
0
0
index.html
<!DOCTYPE html><htmllang="ja"><head><metacharset="utf-8"/><title>TECH::MASTER</title><linkrel="stylesheet"href="reset.css"><linkrel="stylesheet"href="style.css"/><linkhref="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"rel="stylesheet"/></head><body><headerclass="header"><divclass="container"><divclass="header_left"><aclass="header_logo"href="#"><imgclass="logo_img"alt="TECH::MASTER"src="./images/logo.svg"/></a></div><divclass="header_right"><ulclass="header_right_ul"><liclass="header_right_li">お困りの方はこちら
            </li><liclass="header_right_li">カリキュラム変更
            </li><liclass="header_right_li"><imgclass="profile_img"alt="プロフィール画像"src="./images/profile.jpg"></li></ul></div></div></header></body></html>
style.css
body{font-family:"Helvetica Neue",Helvetica,Arial,"Hiragino Sans","ヒラギノ角ゴ Pro W3","HIragino Kaku Gothic Pro W3","HIragino Kaku Gothic Pro",Meryo,"メイリオ",Osaka,"MS Pゴシック","MS P Gothic",sans-serif;font-weight:300;letter-spacing:0.1rem;}.header{margin:40px0;}.container{width:1170px;margin:0auto;display:flex;justify-content:space-between;}.logo_img{height:30px;}.header_right_ul{display:flex;}.header_right_li{font-size:12px;margin:015px;color:#333;line-height:40px;}.profile_img{height:36px;border-radius:50%;border:2pxsolid#eee;}
Viewing all 8498 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>