teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

別解

2020/05/20 08:06

投稿

thyda.eiqau
thyda.eiqau

スコア2982

answer CHANGED
@@ -71,4 +71,73 @@
71
71
  });
72
72
  ```
73
73
 
74
- 全体の幅と高さを固定しておいて、grid-templateを2等分なり3等分なりに変えたほうがいいような気がします。幅を3つに分けるところは5列ずつでいいとしても2つに分けるところが7列・8列になっていて気持ち悪いし……
74
+ 全体の幅と高さを固定しておいて、grid-templateを2等分なり3等分なりに変えたほうがいいような気がします。幅を3つに分けるところは5列ずつでいいとしても2つに分けるところが7列・8列になっていて気持ち悪いし……
75
+
76
+ さらに追記
77
+ ---
78
+ 別解です。gridの子供に指定するのではなく、親のgrid-templateを変えてしまえばよいという考え方です。
79
+ ```css
80
+ .grid-container {
81
+ display: grid;
82
+ width: 100px;
83
+ height: 100px;
84
+ }
85
+ .grid-container[data-children-qty="1"] {
86
+ grid-template: "a" 1fr / 1fr;
87
+ }
88
+ .grid-container[data-children-qty="2"] {
89
+ grid-template:
90
+ "a" 1fr
91
+ "b" 1fr / 1fr;
92
+ }
93
+ .grid-container[data-children-qty="3"] {
94
+ grid-template:
95
+ "a a" 1fr
96
+ "b c" 1fr / 1fr 1fr;
97
+ }
98
+ .grid-container[data-children-qty="4"] {
99
+ grid-template:
100
+ "a b" 1fr
101
+ "c d" 1fr / 1fr 1fr;
102
+ }
103
+ .grid-container[data-children-qty="5+"] {
104
+ grid-template:
105
+ "a a a b b b" 1fr
106
+ "c c d d e e" 1fr / 1fr 1fr 1fr 1fr 1fr 1fr;
107
+ }
108
+ .grid-container > div {
109
+ border: 1px solid #222;
110
+ }
111
+
112
+ /* more */
113
+ .grid-container > div:nth-child(n+6) {
114
+ background-color: gray;
115
+ }
116
+ .grid-container > div:nth-child(n+6) p {
117
+ font-size: 2.5rem;
118
+ display: block;
119
+ position: relative;
120
+ left: 70px;
121
+ top: -170px;
122
+ color: white;
123
+ }
124
+ .grid-container > div:nth-child(n+6) img {
125
+ opacity: 0.6;
126
+ display: block;
127
+ }
128
+ .grid-container > div:nth-child(n+6) a {
129
+ color: white;
130
+ text-decoration: none;
131
+ }
132
+ ```
133
+
134
+ ```js
135
+ document.querySelectorAll('.grid-container').forEach(container => {
136
+ const children = container.querySelectorAll(':scope > div');
137
+ if(children.length === 0) return;
138
+
139
+ container.dataset.childrenQty = children.length >= 5? '5+' : children.length;
140
+ children.forEach((div, idx) => div.style.gridArea = 'abcde'.split('')[idx]);
141
+ });
142
+ ```
143
+ - [CodePen](https://codepen.io/eiqau/pen/YzydERB)

1

要件にあうコードを追記

2020/05/20 08:06

投稿

thyda.eiqau
thyda.eiqau

スコア2982

answer CHANGED
@@ -18,4 +18,57 @@
18
18
  console.log('> adding class name', className);
19
19
  container.classList.add(className);
20
20
  });
21
- ```
21
+ ```
22
+
23
+ 追記
24
+ ---
25
+ 正直、クラスで指定するのが簡単か(やりやすいか・わかりやすいか)というと微妙な気がしますが……
26
+ ```js
27
+ // .grid-contaner の要素を取得し、forEachで回す
28
+ // 本筋とは関係ないですが、grid-conta"i"nerでは?
29
+ document.querySelectorAll('.grid-contaner').forEach(container => {
30
+ // 画像の数は querySelectorAll('img').length で取得してもよいが、
31
+ // 将来的にimg以外の要素が入ってくる可能性を考慮して、直下のdivの数で取得する
32
+ const children = container.querySelectorAll(':scope > div');
33
+ if(children.length === 0) return;
34
+
35
+ container 直下の <div> を取得し、forEachで回す
36
+ container.querySelectorAll(':scope > div').forEach((gridItem, idx) => {
37
+ switch(idx) {
38
+ case 0:
39
+ // 1つ目は基本的にはitem1
40
+ gridItem.className = 'item1';
41
+
42
+ // 画像の数が1つのときはitem10, 2つのときはitem9
43
+ if(children.length <= 2) {
44
+ gridItem.className = `item${11-children.length}`;
45
+ }
46
+ break;
47
+ case 1:
48
+ // 2つ目は基本的にはitem2
49
+ gridItem.className = 'item2';
50
+
51
+ // 画像の数が2つのときはitem8
52
+ if(children.length === 2) gridItem.className = `item8`;
53
+ break;
54
+ case 2:
55
+ case 3:
56
+ case 4:
57
+ // 3つ目から5つ目は基本的にはitem${idx+1}
58
+ gridItem.className = `item${idx+1}`;
59
+
60
+ // 画像の数が4つのときはitem${idx+4}
61
+ if(children.length === 4) gridItem.className = `item${idx+4}`;
62
+
63
+ // 画像の数が3つのときの3つ目はitem8
64
+ if(children.length === 3 && idx === 2) gridItem.className = 'item8';
65
+ break;
66
+ default:
67
+ // 画像が6つ目以降のとき (idxが0から4ではないとき) はここで指定
68
+ gridItem.className = 'more';
69
+ }
70
+ });
71
+ });
72
+ ```
73
+
74
+ 全体の幅と高さを固定しておいて、grid-templateを2等分なり3等分なりに変えたほうがいいような気がします。幅を3つに分けるところは5列ずつでいいとしても2つに分けるところが7列・8列になっていて気持ち悪いし……