質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.97%

HTML Gridレイアウトのセルに対してborderなどの設定

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 256

brsice

score 13

下記のようなアイテム要素の大きさがセルの大きさと異なるGridレイアウトを作成した場合に、Gridのセルに対してスタイル操作を行いたい場合です。
この例ではGridである必要はありませんが、要するに決められた場所にそれより小さい要素を置きたい場合を考えています。

左側のセルにはコンテナを設定しており、アイテムの位置指定やボーダー、背景色など、コンテナを設定すれば簡単に設定できます。
それに対して右側のセルにはコンテナを設定していません。
アイテムの位置指定はレイアウトのオプションでできたものの、ボーダーや背景色の設定はできるのでしょうか?

というのも、Gridで大枠のレイアウトを決め、セルの中にFlexboxなどでさらに要素を詰め込んでいったのですが、大きさの異なる要素をまとめたものの位置を調整して背景を設定してmarginを設定して・・・、と設定していくとコンテナだらけになってしまい、この方針は正しいのか疑問に感じました。
編集しやすいだけならコンテナを増やせば良いと思うのですが、要素が増えることでパフォーマンスに影響を及ぼすのではと考えています。

<div id="grid">
  <div id="container1">
    <div id="item1">
    </div>
  </div>
<!--   <div id="container2"> -->
    <div id="item2"></div>
<!--   </div> -->
</div>
#grid{
  display: grid;
  grid-template-rows: 200px;
  grid-template-columns: 200px 200px;
}
#container1{
  display: flex;
  align-items: center;
  justify-content: center;
  background: gray;
  border: 2px solid black;
}
#item1{
  background: blue;
  width: 50px;
  height: 50px;
}
#item2{
  background: red;
  width: 50px;
  height: 50px;
  justify-self: center;
  align-self: center;
}


イメージ説明


s8_chuさんの回答に対して追記

Flexboxを使った方が良いという点について

今回のような例ではFlexboxを使ったほうが良いというのは重々承知です。
実際には、トップバーやサイドバー等をGridを用いてレイアウトし、グリッドの内部にFlexboxで各要素をレイアウトしたのですが、バーに対してborderやmarginを設定したいと思ったのがきっかけです。
質問用に似たような状況になるコードを書いたのですが、簡単すぎて最初からスペースを指定する意味がないものになってしまいました。
長いコードをそのまま乗せるわけにもいかないですし難しいですね・・・。
少なくともGridで作成するのは明らかにおかしいと言われるようなレイアウトではないと思います。

要素の数がパフォーマンスに与える影響について

Javascriptで動的に要素を変化させようと考えているのですが、操作のレスポンスに少しでも影響がないようにと思い、要素の増加によるパフォーマンスの影響を懸念しました。
他言語的に考えると、DOM要素の移動等の操作を行う際、オブジェクト(要素)をコピーして移動させるか、あるいは参照先を付け替えるだけかと思うのですが、これに関する記述を見つけられませんでした。
もし前者なら、多くの要素を持つコンテナの作成・操作を行うと、大量にコピーが発生するのではと考えました。
「かなり大量に」と表現されているので、10~20程度の要素を内包するコンテナを50~100程度表示させることになると思いますが、この程度なら問題ないと考えてよいでしょうか。
もしDOM操作の仕組みについてもご存知でしたら教えていただけると嬉しいです。

回答のコードについて

3つも紹介していただいてありがとうございます。
いくつか方法はあるのですね。
確かにこの中なら疑似要素を用いたものが使いやすそうです。
直感的にも分かりやすくてありがたいです。
仮にs8_chuさんが同様の操作を行いたい場合、コンテナの作成も含めてどのように実現されますか?
ソースがないので難しいとは思いますが、HTMLやレイアウトを変えても問題ありません。
(上に書いたように2次元的な配置なのでGridが向いていると考えましたが、Gridのセルの代わりにコンテナを作成すれば、Flexboxで敷き詰めても無理なくレイアウトできる程度です。)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+5

かなり大量の要素を扱うのであれば、通信時間のコストが大きくなるかもしれませんが、要素数がパフォーマンス低減の直接的な原因になることは少ないと思います。

また、flexbox を用いて簡単に実現出来ることを flexbox を使わずに行なうと、HTML が簡素になる代わりに、CSS が複雑になることがあります。そのため、状況に応じて flexbox を使用するかどうかを判断すると良いと思います。


今回の場合、flex コンテナを用いずに質問者さんの実現したいことを行なう方法は、いくつか存在します。

1 つ目は、background-clip プロパティと padding プロパティを使用する方法です(動作確認用リンク)。これは Grid トラック、Grid アイテム、border のサイズから padding プロパティに設定する値を算出しています。

#grid {
  --grid-size: 200px;
  display: grid;
  grid-template-rows: var(--grid-size);
  grid-template-columns: var(--grid-size) var(--grid-size);
  grid-gap: 5px;
}

#container1 {
  display: flex;
  align-items: center;
  justify-content: center;
  background: gray;
  border: 2px solid black;
}

#item1 {
  background: blue;
  width: 50px;
  height: 50px;
}

#item2 {
  --border-width: 2px;
  --item-size: 50px;
  background: red;
  width: var(--item-size);
  height: var(--item-size);
  justify-self: center;
  align-self: center;
  background-clip: content-box;
  padding: calc((var(--grid-size) - var(--item-size)) / 2 - var(--border-width));
  border: var(--border-width) solid;
}

2 つ目は、border プロパティと outline プロパティを使用する方法です(動作確認用リンク)。具体的な方法は 1 つ目の方法とほとんど変わりません。

#grid {
  --grid-size: 200px;
  display: grid;
  grid-template-rows: var(--grid-size);
  grid-template-columns: var(--grid-size) var(--grid-size);
  grid-gap: 5px;
}

#container1 {
  display: flex;
  align-items: center;
  justify-content: center;
  background: gray;
  border: 2px solid black;
}

#item1 {
  background: blue;
  width: 50px;
  height: 50px;
}

#item2 {
  --border-width: 2px;
  --item-size: 50px;
  background: red;
  width: var(--item-size);
  height: var(--item-size);
  justify-self: center;
  align-self: center;
  border: calc((var(--grid-size) - var(--item-size)) / 2 - var(--border-width)) solid gray;
  outline: var(--border-width) solid;
}

3 つ目は、#item2 に beforeafter 擬似要素を重ねる方法です(動作確認用リンク)。個人的に、これは上記 2 つよりも扱いやすいと思います。

#grid {
  display: grid;
  position: relative;
  grid-template-columns: 200px 200px;
  grid-template-rows: 200px;
  grid-gap: 5px;
}

#grid > div {
  color: white;
  text-align: center;
}

#container1 {
  display: flex;
  border: 2px solid black;
  background: gray;
}

#item1 {
  width: 50px;
  height: 50px;
  margin: auto;
  background: blue;
}

#item2 {
  width: 50px;
  height: 50px;
  margin: auto;
  background: red;
}

#item2::after {
  z-index: -1;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  border: 2px solid #000;
  background: silver;
  content: "";
  grid-column: 2 / 3;
  grid-row: 1 / 2;
}

ここでは 3 つの方法を紹介しましたが、いずれも flexbox を用いる場合よりも CSS が複雑になっていることに注意してください。

これらの方法は、どうしても HTML 構造を変更出来ず、CSS のみで対応しなければならない場合にのみ使うべきです。もし HTML 構造を変更出来るのであれば、flexbox や CSS Grid Layout を使うことが、HTML, CSS を簡潔に保つ良い方法だと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/21 16:35

    読んで頂きありがとうございます。
    概ね理解しました。
    不親切な質問になってしまい申し訳ありません。
    パフォーマンス部分についてはコードを作成するごとに質問するわけにもいかないので、実際に作成してみて動作が遅くなってしまい、どうしても解決したいという場合に質問させていただこうと思います。

    この質問でさらに具体的なコードをお聞きするのは失礼かと思いますので、方針としてお聞きしたいです。
    要素数は一般的であると仮定して、コンテナを1つ増やしてまとめることで簡潔な記述ができるようになる場合、そちらについて優先的に考えてみるべきですか?

    キャンセル

  • 2019/06/21 18:24

    > 要素数は一般的であると仮定して、コンテナを1つ増やしてまとめることで簡潔な記述ができるようになる場合、そちらについて優先的に考えてみるべきですか?

    基本的には、そのようにすると良いと思います。

    要素のネストが多少深くなったとしても、パフォーマンス面での悪影響が顕著に現われることは滅多にありません。

    また、ネストが深くなることで HTML が読みづらくなってしまう問題については、Haml や Slim などのテンプレートエンジンを用いて対処出来ます。

    キャンセル

  • 2019/06/23 17:10

    少しパフォーマンスに対して敏感になりすぎていたようですね。
    これからは要素を増やすことの簡潔さ,便利さを活用していきたいと思います。
    ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.97%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる