2

My question is identical to this question, but the given solution does not work.

Here is a codepen of what I'm working with.

I've tried two different approaches, both of which are almost correct but not quite:

1. Applying ::before and ::after psuedo classes to first and last grid items

Unfortunately when I add margin-left and margin-right properties to the first and last grid item respectively, it adds the space to the grid items as if it were padding space and not margin space, otherwise this works fine.

2. Applying ::before and ::after psuedo classes to grid container

It will not allow me to manipulate the width of ::before. For some reason the width property of ::before does not take effect. Notably, it seems as if the value of its width is the same width value as any given grid item.

I noticed another peculiarity, which is ultimately irrelevant, with this approach too. If I apply a width to ::after, grid-gap also gets applied as if it is inserting an invisible grid item.

:root {
  --gap: 25px;
}

body {
  width: 100vw;
  overflow-x: hidden;
  margin: 0
}

#c {
  width: 100%;
  height: 50px;
  overflow-x: auto;
  display: grid;
  grid-gap: 20px;
  grid-auto-flow: column;
  grid-auto-columns: calc(calc(100% - calc(var(--gap) * 2)) / 1.5);
  border: solid red 1px;
}

/* second approach */
#c::before {
  content: '';
  width: var(--gap);
}

#c::after {
  content: '';
  width: 1px; /* works out to about 25px or var(--gap) */
}

.i {
  width: 100%;
  height: 25px;
}

/* first approach */
/*
.i:first-child::before {
  content: '';
  margin-left: var(--gap);
}

.i:last-child::after {
  content: '';
  margin-right: var(--gap);
}
*/

.i:nth-child(odd) {
  background: skyblue;
}

.i:nth-child(even) {
  background: pink;
}
<div id='c'>
  <div class='i'>1</div>
  <div class='i'>2</div>
  <div class='i'>3</div>
  <div class='i'>4</div>
  <div class='i'>5</div>
  <div class='i'>6</div>
  <div class='i'>7</div>
  <div class='i'>8</div>
  <div class='i'>9</div>
  <div class='i'>10</div>
  <div class='i'>11</div>
  <div class='i'>12</div>
  <div class='i'>13</div>
  <div class='i'>14</div>
  <div class='i'>15</div>
  <div class='i'>16</div>
  <div class='i'>17</div>
  <div class='i'>18</div>
  <div class='i'>19</div>
  <div class='i'>20</div>
  <div class='i'>21</div>
  <div class='i'>22</div>
  <div class='i'>23</div>
  <div class='i'>24</div>
</div>

Does anybody have any idea why this stuff is happening?

How can I change the width of ::before?

oldboy
  • 5,729
  • 6
  • 38
  • 86
  • 1
    the before element is simply a grid element so it will take the same width defined for the other element (note that element is inside a grid track so its width is defined inside another hidden wrapper) – Temani Afif Mar 17 '19 at 20:25
  • @TemaniAfif but why will it allow me to manipulate the `width` of `::after` which also seems to be a grid element? and how can i change the width of `::before`? – oldboy Mar 17 '19 at 20:29
  • not sure about this one something to do with overflow probably – Temani Afif Mar 17 '19 at 20:29
  • @TemaniAfif i would suspect it prolly has something to do with `auto-flow` and `auto-columns` and not overflow? – oldboy Mar 17 '19 at 20:31
  • i am not really sure, I will try to see more .. but technically (per my understanding) it should have the same width as the other. I am probably missing something trivial – Temani Afif Mar 17 '19 at 20:36
  • 1
    yes it's for sure overflow. The track is having the correct width but overflow is not considering the width of the track but only the element width. Basically `after` is behaving the same as `before` but its track is overflowing and not counted inside the scrolling area. – Temani Afif Mar 17 '19 at 20:41
  • @TemaniAfif oh wow. i wonder if thats considered a "bug" or if theyll end up changing that within the browser implementation of css3 grids?? – oldboy Mar 17 '19 at 20:47
  • or probably it's by design, I am trying to find if there is anything describing this in the spec – Temani Afif Mar 17 '19 at 20:49
  • @TemaniAfif not very user friendly if it is by design – oldboy Mar 17 '19 at 21:58

2 Answers2

2

One idea to change the width of before is to define a column template like below that will force the width of the first element only then the other will follow the grid-auto-columns. Basically we define an explicit grid with 1 column then the browser will add more column as needed to create the implicit grid:

:root {
  --gap: 25px;
}

body {
  width: 100vw;
  overflow-x: hidden;
  margin: 0
}

#c {
  width: 100%;
  height: 50px;
  overflow-x: auto;
  display: grid;
  grid-gap: 20px;
  grid-template-columns:1px;
  grid-auto-flow: column;
  grid-auto-columns: calc(calc(100% - calc(var(--gap) * 2)) / 1.5);
  border: solid red 1px;
}

/* second approach */
#c::before {
  content: '';
}

#c::after {
  content: '';
  width: 1px; /* works out to about 25px or var(--gap) */
}

.i {
  /*width: 100%; not needed*/
  height: 25px;
  /*display: inline-block; not needed*/
}

.i:nth-child(odd) {
  background: skyblue;
}

.i:nth-child(even) {
  background: pink;
}
<div id='c'>
  <div class='i'>1</div>
  <div class='i'>2</div>
  <div class='i'>3</div>
  <div class='i'>4</div>
  <div class='i'>5</div>
  <div class='i'>6</div>
  <div class='i'>7</div>
  <div class='i'>8</div>
  <div class='i'>9</div>
  <div class='i'>10</div>
  <div class='i'>11</div>
  <div class='i'>12</div>
  <div class='i'>13</div>
  <div class='i'>14</div>
  <div class='i'>15</div>
  <div class='i'>16</div>
  <div class='i'>17</div>
  <div class='i'>18</div>
  <div class='i'>19</div>
  <div class='i'>20</div>
  <div class='i'>21</div>
  <div class='i'>22</div>
  <div class='i'>23</div>
  <div class='i'>24</div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
1

This is another one of those instances where flexbox may provide a simpler, easier and more effective solution that grid.

:root {
  --gap: 25px;
}

#c {
  display: flex;
  overflow-x: auto;
  height: 50px;
  border: solid red 1px;
}

.i {
  height: 25px;
  flex: 0 0 calc(calc(100% - calc(var(--gap) * 2)) / 1.5); /* fg, fs, fb */
}

#c::before {
  content: '';
  flex: 0 0 var(--gap);
}

.i {
  margin-right: 20px;
}

#c::after {
  content: '';
  flex: 0 0 calc(var(--gap) - 20px); /* gap less margin */
}

.i:nth-child(odd)  { background: skyblue; }
.i:nth-child(even) { background: pink; }
body               { margin: 0; }
*                  { box-sizing: border-box; }
<div id='c'>
  <div class='i'>1</div>
  <div class='i'>2</div>
  <div class='i'>3</div>
  <div class='i'>4</div>
  <div class='i'>5</div>
  <div class='i'>6</div>
  <div class='i'>7</div>
  <div class='i'>8</div>
  <div class='i'>9</div>
  <div class='i'>10</div>
  <div class='i'>11</div>
  <div class='i'>12</div>
  <div class='i'>13</div>
  <div class='i'>14</div>
  <div class='i'>15</div>
  <div class='i'>16</div>
  <div class='i'>17</div>
  <div class='i'>18</div>
  <div class='i'>19</div>
  <div class='i'>20</div>
  <div class='i'>21</div>
  <div class='i'>22</div>
  <div class='i'>23</div>
  <div class='i'>24</div>
</div>

You may also want to consider a transparent border for start- and end-side spacing. Last margin / padding collapsing in flexbox / grid layout

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • thanks for the suggestion, but grid is far superior in this situation due to `grid-gap`. and everything is working perfectly now. the problem with flex is that u always have to add margin or padding and continually adjust them – oldboy Mar 17 '19 at 23:55
  • 1
    Right. In this situation. But maybe not in others. That's why I posted the answer. Plus, the [`gap` property](https://www.w3.org/TR/css-align-3/#gap-shorthand) is expected to be available in flex containers. – Michael Benjamin Mar 17 '19 at 23:58
  • thats what i figured, but ive found that in most situations for me personally grid is far superior to flex. ***expected*** to be available in flex containers? when? – oldboy Mar 18 '19 at 00:22
  • I would guess before the end of this year, but I have no inside information. – Michael Benjamin Mar 18 '19 at 00:33
  • And Grid is a superior technology. But [flex still has advantages](https://stackoverflow.com/q/55064488/3597276). – Michael Benjamin Mar 18 '19 at 00:34
  • definitely!! im sure flex still has its moments, but theyre few and far between now imo. – oldboy Mar 18 '19 at 00:37