- 投稿日:2020-09-25T23:05:17+09:00
【Rails6.0】突然CSSが読み込まれなくなった、、【怪奇現象?】
現在個人開発で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に送信 upstream webapp { # ソケット通信したいのでpuma.sockを指定 server unix:///webapp/tmp/sockets/puma.sock; } server { listen 80; # ドメインもしくはIPを指定 server_name webapp ; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log; # ドキュメントルートの指定 root /webapp/public; client_max_body_size 100m; error_page 404 /404.html; error_page 505 502 503 504 /500.html; try_files $uri/index.html $uri @webapp; keepalive_timeout 5; # リバースプロキシ関連の設定 location @webapp { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://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読み込みがうまくいかないとかならまだわかるんですが、今回は突然のエラーだったので治すのに時間がかかってしまいました。同じエラーに遭遇している方に、こちらが役に立てばうれしいです!
- 投稿日:2020-09-25T21:56:58+09:00
【作ってみた】js不使用。CSSだけでマウスホバーで動く自動ドア作った。
どうも7noteです。電車に乗っていてふと突然、「そうだ自動ドア作ろう」って思ったので作ってみた。
完成予定イメージ
ソース
予想していたよりも短くコンパクトに書けました。
index.html<div class="doors"> <div class="door left"></div> <div class="door right"></div> </div>style.css.doors { width: 200px; /* ドア2枚分の横幅 */ height: 300px; /* ドアの高さ */ overflow: hidden; /* 空いたとき、ドアを消す為のもの。 */ border: solid 2px #000; /* ドア全体の枠線 */ display: flex; /* 2枚のドアを横並びにする */ } .door { background: linear-gradient(-135deg, #AAD5EE 50%, #FFF 50%, #FFF 60%, #AAD5EE 60%); /* グラデーションを使ってガラスっぽさを表現 */ width: 100px; /* ドア1枚分の横幅 */ height: 300px; /* ドアの高さ */ border: solid 1px #EEE; /* ドアの枠線 */ box-sizing: bordre-box; /* 余白の計算を簡単にするため */ transition: all .5s; /* ドアがゆっくり開く */ } .doors:hover .left{ transform: translateX(-97%); /* マウスホバー時に、左に動く */ } .doors:hover .right { transform: translateX(97%); >/* マウスホバー時に、右に動く */ }解説
とっても簡単にそれっぽく見せることができました。
実際にガラスのように透かして見せる場合はbackground
の#AAD5EE
を全てrgba(0,153,255,0.4)
くらいに変えてください。
時間帯によって、ガラスの色合いが変わるとかになったら綺麗かも。そうなるとCSSだけじゃ厳しいか・・・おそまつ!
~ Qiitaで毎日投稿中!! ~
【初心者向け】HTML・CSSのちょいテク詰め合わせ
- 投稿日:2020-09-25T21:08:38+09:00
[CSS] flex align-itemsの混合の方法
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
- 投稿日:2020-09-25T20:45:36+09:00
Tyハロトレ27日目
CSS
repeat-x
bg-attachment
bg-size
ショートハンド
拡張子
png・・・可逆圧縮(元に戻せまっせ)
jpeg・・・データを一部捨てているので、不可逆的圧縮(元に戻せんわい)
gif・・・べた塗りのイラストによく使います。bdrs
text-shadow
h1 { text-shadow: x方向の距離 y方向の距離 ぼかし幅 影色; }box-shadow
h1 { box-shadow: x方向の距離 y方向の距離 ぼかし幅 (広がり) 影色 (内側指定); }「rgba」の最後の「a」はアルファ値(alpha)で不透明度を表すのによく使います。
linear-gradient
線形グラデーションを表します。radial-gradientは、円形グラデーションを表します。
to bottom
は下方向へという意味になります。h1{ background-image: linear-gradient(開始位置(xxx方向へ), 開始色, 終了色); }Google Fonts
index.html<link href="https://fonts.googleapis.com/css2?family=Limelight&display=swap" rel="stylesheet">style.cssh1 {font-family: 'Limelight', cursive;}Photoshop
ショートカット
Ctrl + スペースキーでズーム
スクロール
色調補正
選択ツール
選択ツールにあるマークは、マジックワンド wand なので、ショートカット「w」キー
Ctrl + D で選択解除切り抜きコピー
透明な部分を編集できないようにする
塗りつぶし
ぼかし(ガウス)
影の色を調節
遠近法
ワープ
乗算
自由な形に
半分を選択
Ai(ベクトル) → Ps(ビットマップ)
変換
illustratorのレイヤーを全て選択してコピー
Photoshopに貼り付けすると、下記画像のような画面が出て、ピクセルを選びます。
illustratorのファイルも画像と同じように加工できます。
ガイドをロック
- 投稿日:2020-09-25T18:58:31+09:00
displayとpositionの不思議な関係
inline
要素にposition: absolute
を指定すると自動的にdisplay:block
になることに気づいたので他のpositionプロパティだとどうなるの?って感じで調べてみた。(常識? w3cのドキュメントに書いてあるのかもしれないけど見てない)
position: absolute
とposition: fixed
の場合にdisplay
プロパティの変化が起こる模様
inline
<->block
inline-flex
<->flex
inline-table
<->table
...全部の
display
プロパティは調べてません。
- 投稿日:2020-09-25T07:16:02+09:00
Styled-componentsでシンプルにグリッドレイアウトを実装する
はじめに
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.tsimport { createGlobalStyle } from 'styled-components/macro'; export const GlobalStyle = 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.tsimport { createGlobalStyle } from 'styled-components/macro'; export const GlobalStyle = 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.tsximport React from 'react'; import styled from 'styled-components/macro'; import { GlobalStyle } from './GlobalStyle'; import './App.css'; // configs const breakpoints: { sm: number; md: number; lg: number; xl: number } = { sm: 576, md: 768, lg: 992, xl: 1280, }; const containerMaxWidths: { sm: number; md: number; lg: number; xl: number } = { sm: 540, md: 720, lg: 960, xl: 1250, }; const gridColumns: number = 12; const gridGutterWidth: number = 32; // components function App() { return <div><GlobalStyle /></div>; } export default App;4. 汎用コンポーネント作成
汎用的に使うコンテナのコンポーネントと、グリッド行・グリッド列のコンポーネントを用意します。
実装にあたりBootstrapのscssやcssのソースを参考にしました。
全て理解するのは難解ですが、一つ一つは(Bootstrapを使うかに関係なく)CSSの設計に勉強になることが多いと感じます。App.tsximport React from 'react'; import styled from 'styled-components/macro'; import { GlobalStyle } from './GlobalStyle'; import './App.css'; // configs const breakpoints: { sm: number; md: number; lg: number; xl: number } = { sm: 576, md: 768, lg: 992, xl: 1280, }; const containerMaxWidths: { sm: number; md: number; lg: number; xl: number } = { sm: 540, md: 720, lg: 960, xl: 1250, }; const gridColumns: number = 12; const gridGutterWidth: number = 32; // components const Container = 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; `; const Row = styled.div` display: flex; flex-wrap: wrap; margin-right: ${-gridGutterWidth / 2}px; margin-left: ${-gridGutterWidth / 2}px; `; type ColProps = { sizeDefault: number; sizeSm?: number; sizeMd?: number; sizeLg?: number; sizeXl?: number; }; const Col = 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; `; function App() { return <div><GlobalStyle /></div>; } export default App;ここで各コンポーネントの解説をします。
なお前提として、モバイルファーストで作っています。
Container
コンポーネント幅はブレークポイントに対応する最大幅を設定します。
中央寄せした上で、グリッド溝/2を左右のpadding
に与えます。
Row
コンポーネントはじめに
display
をflex
にセットして、
グリッド溝/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: 1px solid #000; border-left: 1px solid #000; }App.tsximport React from 'react'; import styled from 'styled-components/macro'; import { GlobalStyle } from './GlobalStyle'; import './App.css'; // configs const breakpoints: { sm: number; md: number; lg: number; xl: number } = { sm: 576, md: 768, lg: 992, xl: 1280, }; const containerMaxWidths: { sm: number; md: number; lg: number; xl: number } = { sm: 540, md: 720, lg: 960, xl: 1250, }; const gridColumns: number = 12; const gridGutterWidth: number = 32; // components const Container = 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; `; const Row = styled.div` display: flex; flex-wrap: wrap; margin-right: ${-gridGutterWidth / 2}px; margin-left: ${-gridGutterWidth / 2}px; `; type ColProps = { sizeDefault: number; sizeSm?: number; sizeMd?: number; sizeLg?: number; sizeXl?: number; }; const Col = 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; `; // Usage const Heading = styled.h1` font-size: 32px; font-weight: bold; padding: 24px 0; `; type InnerContentProps = { height: number; backgroundColor: string }; const InnerContent = styled.div<InnerContentProps>` height: ${(props) => props.height}px; background-color: ${(props) => props.backgroundColor}; `; function App() { return ( <div> <GlobalStyle /> <Container className="side-border"> <Heading>12 Grid system</Heading> <Row> {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((v, index) => ( <Col key={index} sizeDefault={1}> <InnerContent height={600} backgroundColor="deepskyblue"></InnerContent> </Col> ))} </Row> <Heading>Responsive 1</Heading> <Row> <Col sizeDefault={12} sizeMd={4} sizeLg={4} sizeXl={4}> <InnerContent height={200} backgroundColor="lightgray"></InnerContent> </Col> <Col sizeDefault={12} sizeMd={4} sizeLg={4} sizeXl={4}> <InnerContent height={200} backgroundColor="darkgray"></InnerContent> </Col> <Col sizeDefault={12} sizeMd={4} sizeLg={4} sizeXl={4}> <InnerContent height={200} backgroundColor="gray"></InnerContent> </Col> </Row> <Heading>Responsive 2</Heading> <Row> <Col sizeDefault={12} sizeMd={12} sizeLg={4} sizeXl={4}> <InnerContent height={300} backgroundColor="gold"></InnerContent> </Col> <Col sizeDefault={12} sizeMd={12} sizeLg={8} sizeXl={8}> <InnerContent height={300} backgroundColor="goldenrod"></InnerContent> </Col> </Row> <Heading>Responsive 3</Heading> <Row> <Col sizeDefault={12} sizeLg={8} sizeXl={8}> <Row> <Col sizeDefault={6}> <InnerContent height={150} backgroundColor="blue"></InnerContent> </Col> <Col sizeDefault={6}> <InnerContent height={150} backgroundColor="darkblue"></InnerContent> </Col> <Col sizeDefault={6}> <InnerContent height={150} backgroundColor="dodgerblue"></InnerContent> </Col> <Col sizeDefault={6}> <InnerContent height={150} backgroundColor="royalblue"></InnerContent> </Col> </Row> </Col> <Col sizeDefault={12} sizeLg={4} sizeXl={4}> <InnerContent height={300} backgroundColor="crimson"></InnerContent> </Col> </Row> </Container> </div> ); } export default App;上記を出力するとこのようになります。
実際の動きは下記GitHubからリンクを参照してください。