Как разместить нечетные элементы в сетке во всех строках определенного столбца и четные элементы в другом столбце? - PullRequest
0 голосов
/ 09 ноября 2019

Поэтому я пытаюсь создать временную шкалу с помощью CSS для своего онлайн-резюме. Мой план состоит в том, чтобы сделать сетку с двумя основными столбцами и третьим столбцом между ними для линии и ее стиля. Я хочу разместить все остальные элементы на правой стороне линии (третий столбец сетки). Есть ли способ использовать :nth-child(odd) или что-то подобное, чтобы добиться этого? Я, конечно, могу использовать grid-area, но я бы предпочел не размещать каждый элемент по отдельности.

Это моя текущая сетка:

.timeline {
  display: grid;
  grid-template-columns: 49% 2px auto;
  grid-template-rows: repeat(5, 1fr);
  grid-template-areas:
      "event1 line . "
      " . line event2"
      "event3 line . "
      " . line event4"
      "event5 line . "
      " . line event6";
  text-align: center;
}

.line {
  grid-area: line;
  background-color: black !important;
  margin: 0 !important;
  padding: 0 !important;
}

.timeline :nth-child(2) {
  grid-area: event1;
}

.timeline :nth-child(3) {
  grid-area: event2;
}

.timeline :nth-child(4) {
  grid-area: event3;
}

.timeline :nth-child(5) {
  grid-area: event4;
}

.timeline :nth-child(6) {
  grid-area: event5;
}

.timeline :nth-child(7) {
  grid-area: event6;
}

Это работает, но должно быть большеэффективный способ сделать это.

Ответы [ 2 ]

0 голосов
/ 09 ноября 2019

Один из подходов заключается в следующем.

const addTask = () => {
  const D = document,
    timeline = D.querySelector('ol.timeline'),
    taskElement = D.createElement('li'),
    span = D.createElement('span'),
    div = D.createElement('div');

  span.classList.add('connection');
  div.textContent = timeline.children.length + 1;
  taskElement.append(span, div);
  timeline.appendChild(taskElement);
}

document.querySelector('#addEntry').addEventListener('click', addTask);
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

button {
  display: block;
  width: 80vw;
  margin: 0.5em auto;
  height: 2em;
  line-height: 2em;
}

:root {
  --timeline_connector_position: 30%;
  --timeline_margin: auto;
  --timeline_gapSize: 0.2rem 0rem;
  --timeline_centre: 5vw;
  --timeline_width: 90vw;
  --timeline_padding: 0.5rem;
  --timeline_taskBackground: #fff;
  --timeline_taskBackground_even: #f90;
  --timeline_taskBackground_odd: limegreen;
  --timeline_taskBorder: 1px solid #000;
  --timeline_taskBorder_even: 1px solid #000;
  --timeline_taskBorder_odd: 1px solid #000;
  --timeline_color: brown;
}

ol,
li {
  list-style-type: none;
}

ol.timeline {
  display: grid;
  width: var(--timeline_width);
  margin: var(--timeline_margin);
  grid-template-columns: 1fr var(--timeline_centre) 1fr;
  grid-gap: var(--timeline_gapSize);
  background: linear-gradient( to right, transparent, transparent calc(50% - var(--timeline_centre)/6), var(--timeline_color) calc(50% - var(--timeline_centre)/6), var(--timeline_color) calc(50% + var(--timeline_centre)/6), transparent calc(50% + var(--timeline_centre)/6), transparent);
}

li {
  display: grid;
  grid-gap: var(--timeline_gapSize);
}

li:nth-child(odd) {
  grid-area: auto / 1 / auto / span 2;
  grid-template-columns: 1fr var(--timeline_centre);
  grid-template-areas: "text connection";
}

li:nth-child(even) {
  grid-area: auto / 2 / auto / span 2;
  grid-template-columns: var(--timeline_centre) 1fr;
  grid-template-areas: "connection text";
}

li>div {
  background-color: var(--timeline_taskBackground);
  padding: var(--timeline_padding);
  grid-area: text;
}

li:nth-child(odd)>div {
  background-color: var(--timeline_taskBackground_odd);
  border: var(--timeline_taskBorder_odd, --timeline_taskBorder);
}

li:nth-child(even)>div {
  background-color: var(--timeline_taskBackground_even);
  border: var(--timeline_taskBorder_even, --timeline_taskBorder);
}

span.connection {
  grid-area: connection;
  background: linear-gradient( to bottom, transparent, transparent calc(var(--timeline_connector_position) - 3px), var(--timeline_color) calc(var(--timeline_connector_position) - 3px), var(--timeline_color) calc(var(--timeline_connector_position) + 3px), transparent calc(var(--timeline_connector_position) + 3px), transparent);
  background-size: 50%;
  background-repeat: no-repeat;
}

li:nth-child(odd)>span.connection {
  background-position: left;
}

li:nth-child(even)>span.connection {
  background-position: right;
}
<button id="addEntry">Add a new entry</button>

<ol class="timeline">
  <li>
    <span class="connection"></span>
    <div>1 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut explicabo quas esse, odio accusantium minus. Asperiores mollitia est, iusto corrupti quibusdam ipsa, assumenda nam id animi quod, nesciunt placeat. Perferendis!</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>2</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>3</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>4</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>5</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>6</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>7</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>8</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>9</div>
  </li>
  <li>
    <span class="connection"></span>
    <div>10</div>
  </li>
</ol>

JS Fiddle demo .

В приведенной выше демонстрации мы размечаем временную шкалу и ееследующие записи:

<!-- use of an ordered list for the timeline itself: -->
<ol class="timeline">
  <!-- each timeline entry is nested within and <li> element: -->
  <li>
    <!-- this could have been replaced by a pseudo-element and, perhaps
         should have been; its use is purely presentational and serves to
         connect the 'task' to the 'timeline' graphic: -->
    <span class="connection"></span>

    <!-- the <div> is used to wrap the text of the timeline entry: -->
    <div>1 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut explicabo quas esse, odio accusantium minus. Asperiores mollitia est, iusto corrupti quibusdam ipsa, assumenda nam id animi quod, nesciunt placeat. Perferendis!</div>
  </li>
  <!-- other entries omitted for brevity -->
</ol>

Причина, по которой мы вложили записи временной шкалы, заключается в основном в том, что подсетка CSS пока не поддерживается в большинстве браузеров, и это простое средство, с помощью которого мы можем сместить<li> записей соответственно, как показано на CSS - -

/* I've used quite a lot of CSS variables for purposes of theming,
   retain or discard at your pleasure! */
:root {
  --timeline_connector_position: 30%;
  --timeline_margin: auto;
  --timeline_gapSize: 0.2rem 0rem;
  --timeline_centre: 5vw;
  --timeline_width: 90vw;
  --timeline_padding: 0.5rem;
  --timeline_taskBackground: #fff;
  --timeline_taskBackground_even: #f90;
  --timeline_taskBackground_odd: limegreen;
  --timeline_taskBorder: 1px solid #000;
  --timeline_taskBorder_even: 1px solid #000;
  --timeline_taskBorder_odd: 1px solid #000;
  --timeline_color: brown;
}

ol.timeline {
  display: grid;
  /* Using some of the defined CSS custom properties to set
     the width and margin: */
  width: var(--timeline_width);
  margin: var(--timeline_margin);

  /* Here we define the three-column layout, comprising of
       column 1: 1 fractional unit,
       column 2: defined by the --timeline_centre custom property,
       column 3: 1 fractional unit: */
  grid-template-columns: 1fr var(--timeline_centre) 1fr;
  grid-gap: var(--timeline_gapSize);
  /* This background defines the 'timeline' vertical stroke: */
  background: linear-gradient(
    /* the gradient moves from left to right: */
    to right,
    /* is transparent at the start of the gradient: */
    transparent,
    /* remains transparent until the point calculated by the
       CSS calc function; here we're calculating a pixel-value of
       50% width of the element, minus the width defined by the
       --timeline_centre value divided by six (the six is arbitrary
       but provided a good-enough visual in the JS Fiddle and Snippet,
       adjust to taste): */
    transparent calc(50% - var(--timeline_centre)/6),
    /* at the same point as above the colour changes to the colour
       defined by the --timeline_color custom property: */
    var(--timeline_color) calc(50% - var(--timeline_centre)/6),
    /* the change here is that we add, rather than subtract the value
       in order that the --timeline_color spans across the 50% mark: */
    var(--timeline_color) calc(50% + var(--timeline_centre)/6),
    /* at the same point that the --timeline_color ends the transparent
       value resumes; this creates hard colour stops rather than
       fading gradients: */
    transparent calc(50% + var(--timeline_centre)/6),
    transparent
  );
}

li {
  display: grid;
  grid-gap: var(--timeline_gapSize);
}

li:nth-child(odd) {
  /* here the odd <li> elements are placed with the syntax of:
       row-start / column-start / row-end / column-end
     in this case the row is placed into its naturally-occuring
     row ('auto'), starts in the first column of the grid (1), ends
     in the naturally-occurring row ('auto') and spans two columns
     ('span 2'): */
  grid-area: auto / 1 / auto / span 2;

  /* we define a two-column grid, of 1 fractional unit, and one
     column equal to the size defined by the --timeline_centre
     custom property: */
  grid-template-columns: 1fr var(--timeline_centre);
  /* we name the two columns of this two-column grid: */
  grid-template-areas: "text connection";
}

li:nth-child(even) {
  /* exactly as above, but the even <li> elements start
     in the second column instead of the first: */
  grid-area: auto / 2 / auto / span 2;
  /* exactly as above but the columns are reversed in order
     that the var(--timeline_centre)/'connection' column
     overlaps the column of the same width in the parent
     grid: */
  grid-template-columns: var(--timeline_centre) 1fr;
  grid-template-areas: "connection text";
}

li>div {
  /* here we use some of the theming options to style the
     element: */
  background-color: var(--timeline_taskBackground);
  padding: var(--timeline_padding);
  /* positioning the timeline entry text in the grid
     area identified by the name 'text': */
  grid-area: text;
}

li:nth-child(odd)>div {
  background-color: var(--timeline_taskBackground_odd);
  border: var(--timeline_taskBorder_odd, --timeline_taskBorder);
}

li:nth-child(even)>div {
  background-color: var(--timeline_taskBackground_even);
  border: var(--timeline_taskBorder_even, --timeline_taskBorder);
}

span.connection {
  grid-area: connection;
  background: linear-gradient( to bottom, transparent, transparent calc(var(--timeline_connector_position) - 3px), var(--timeline_color) calc(var(--timeline_connector_position) - 3px), var(--timeline_color) calc(var(--timeline_connector_position) + 3px), transparent calc(var(--timeline_connector_position) + 3px), transparent);
  background-size: 50%;
  background-repeat: no-repeat;
}

/* here we position the connection background in order that it
   visually connects the timeline entry text to the timeline
   itself: */
li:nth-child(odd)>span.connection {
  background-position: left;
}

li:nth-child(even)>span.connection {
  background-position: right;
}
0 голосов
/ 09 ноября 2019

Если я правильно понимаю, что вы хотите, вы можете использовать nth-child, чтобы установить начало столбца для .line и .event. Однако это создаст дыры, поэтому вам также нужно установить grid-auto-flow: row dense; на .grid. Линия должна заполнить два столбца, поэтому вам необходимо переместить фон в правильное положение для каждого случая.

:root {
  --line-width: 5px;
  --line-height: 3px;
  --main-line-width: calc(var(--line-width) * 2 + 2px);
  --odd-line-color: gold;
  --even-line-color: silver;
}

.timeline {
  display: grid;
  grid-template-columns: 1fr var(--main-line-width) 1fr;
  grid-auto-flow: row dense;
  text-align: center;
}

.line {
  grid-column-start: 2;
  grid-column-end: span 2;
  background: linear-gradient(currentColor, currentColor), 
              linear-gradient(to right, transparent var(--line-width), black var(--line-width), black calc(var(--line-width) + 2px), transparent calc(var(--line-width) + 2px));
  background-repeat: no-repeat;
  background-size: var(--line-width) var(--line-height), 
                   var(--main-line-width) 100%;
  background-position: center left;
  color: var(--odd-line-color)
}

.line:nth-child(4n + 4) {
  grid-column-start: 1;
  background-position: center right;
  color: var(--even-line-color);
}

.event {
  grid-column-start: 1;
  border: var(--line-height) solid var(--odd-line-color);
}

.event:nth-child(4n + 3) {
  grid-column: 3;
  border-color: var(--even-line-color);
}
<div class="timeline">
  <div class="event">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui elit, tincidunt sit amet dictum ut, tempus vel diam. Integer ac sem congue, ullamcorper libero sit amet, viverra dui.</div>
  <div class="line"></div>
  <div class="event">Lorem ipsum dolor sit amet, consectetur adipiscing elit. </div>
  <div class="line"></div>
  <div class="event">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui elit, tincidunt sit amet dictum ut, tempus vel diam.</div>
  <div class="line"></div>
  <div class="event">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui elit, tincidunt sit amet dictum ut, tempus vel diam. Integer ac sem congue, ullamcorper libero sit amet, viverra dui. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui elit, tincidunt sit amet dictum ut, tempus vel diam. Integer ac sem congue, ullamcorper libero sit amet, viverra dui.</div>
  <div class="line"></div>
  <div class="event">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui elit, tincidunt sit amet dictum ut, tempus vel diam. Integer ac sem congue, ullamcorper libero sit amet, viverra dui.</div>
  <div class="line"></div>
  <div class="event">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui elit, tincidunt sit amet dictum ut, tempus vel diam. Integer ac sem congue, ullamcorper libero sit amet, viverra dui.</div>
  <div class="line"></div>
  <div class="event">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui elit, tincidunt sit amet dictum ut, tempus vel diam. Integer ac sem congue, ullamcorper libero sit amet, viverra dui.</div>
  <div class="line"></div>
  <div class="event">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque dui elit, tincidunt sit amet dictum ut, tempus vel diam. Integer ac sem congue, ullamcorper libero sit amet, viverra dui.</div>
  <div class="line"></div>
</div>
...