Rearrange items in a display: contents wrapper using CSS Grid

I'm having trouble positioning descendants in a root grid while they are enclosed in a container with display: contents.

The issue I am facing is that one element is not being correctly placed within the grid:

.wrapper {
  width: 80ch;
  margin: auto;
  margin-top: 4rem;
}

p {
  margin-block-start: 0px;
}

as-question {
  --font-size: 12pt;
  --spacing: 8px;
  width: 100%;
  display: grid;
  font-size: var(--font-size, 12pt);
  gap: var(--spacing, 8px);
  grid-template-columns: [question-number-start] 10mm [question-number-end part-number-start question-content-start] 1.75rem [part-number-end part-content-start subpart-number-start] 1.75rem [subpart-number-end subpart-content-start] auto [part-content-end subpart-content-end question-content-end marks-start] 2rem [marks-end question-end];
}
as-question:before {
  grid-column: question-number-start/question-number-end;
  content: "1.";
  counter-reset: part subpart;
}
as-question .content {
  display: contents;
}
as-question > div.content > :not(as-part):not(as-subpart) {
  grid-column: question-content-start/question-content-end;
}
as-question as-marks {
  grid-column: marks-start/marks-end;
}
as-question as-part {
  display: contents;
}
as-question as-part:before {
  counter-reset: subpart;
  counter-increment: part;
  grid-column: part-number-start/part-number-end;
  content: "(" counter(part, lower-alpha) ")";
  text-align: right;
}
as-question as-part > div.content > :not(as-subpart) {
  grid-column: part-content-start/part-content-end;
}
as-question as-part as-marks {
  color: red;
}
as-question as-subpart {
  display: contents;
}
as-question as-subpart:before {
  counter-increment: subpart;
  grid-column: subpart-number-start/subpart-number-end;
  content: "(" counter(subpart, lower-roman) ")";
  text-align: right;
}
as-question as-subpart > div.content * {
  grid-column: subpart-content-start/subpart-content-end;
}
as-question as-subpart as-marks {
  color: blue;
}
<as-question>
    <div class='content'>
      <p>This is some question content</p>
      <as-part>
        <as-marks>2</as-marks>
        <div class='content'>
          <p>Part: How can I not be pushed down?</p>
          <as-subpart>
            <as-marks>1</as-marks>
            <div class='content'>
              <p>Subpart</p>
            </div>
          </as-subpart>
          <as-subpart>
            <as-marks>1</as-marks>
            <div class='content'>
              <p>Subpart</p>
            </div>
          </as-subpart>
        </div>
      </as-part>
      <as-part>
        <as-marks>6</as-marks>
        <div class='content'>
          <p>Part</p>
          <as-subpart>
            <as-marks>4</as-marks>
            <div class='content'>
              <p>Subpart</p>
            </div>
          </as-subpart>
          <as-subpart>
            <as-marks>2</as-marks>
            <div class='content'>
              <p>Subpart</p>
            </div>
          </as-subpart>
        </div>
      </as-part>
    </div>
  </as-question>

Every time I insert an

<as-marks>{number}</as-marks>
element before a <div class='content'> (which has display: contents;), the first child of
<div class="content">
gets moved to the next row (refer to the image below).

https://i.stack.imgur.com/VTAlM.png

Is there a way to ensure the first child of <div class='content'> is placed on the same line as the marks?

Although I could revert to using grids within grids within grids, this approach seemed more organized. Looking forward to the implementation of subgrid.

Codepen for testing

If you're wondering about the unconventional HTML structure, it's because I aim to utilize Prosemirror with custom NodeViews, and this is how Prosemirror structures the resulting HTML.

Answer №1

Here are a couple of key points:

1. The grid auto-placement algorithm

The

<div class="content">
element is moved to the next line because its natural placement in the grid remains unchanged.

In simpler terms, it flows naturally to the next line based on its position in the HTML code after certain elements.

Unless specified otherwise (e.g., using grid-row: 2), the grid auto-placement algorithm takes control.

2. Using grid-auto-flow: dense

To address this issue, the grid design includes a useful feature.

By applying grid-auto-flow: dense, the algorithm prioritizes filling empty spaces earlier within the grid layout.

Ensure to add this line of code to your grid container for optimal results.

Below is an updated version of your code with one modification and the compiled CSS:

.wrapper {
  width: 80ch;
  margin: auto;
  margin-top: 4rem;
}

p {
  margin-block-start: 0px;
}

as-question {
  --font-size: 12pt;
  --spacing: 8px;
  width: 100%;
  display: grid;
  font-size: var(--font-size, 12pt);
  gap: var(--spacing, 8px);
  grid-template-columns: [question-number-start] 10mm [question-number-end part-number-start question-content-start] 1.75rem [part-number-end part-content-start subpart-number-start] 1.75rem [subpart-number-end subpart-content-start] auto [part-content-end subpart-content-end question-content-end marks-start] 2rem [marks-end question-end];
  grid-auto-flow: dense; /* NEW */
}
as-question:before {
  grid-column: question-number-start/question-number-end;
  content: "1.";
  counter-reset: part subpart;
}
as-question .content {
  display: contents;
}
as-question > div.content > :not(as-part):not(as-subpart) {
  grid-column: question-content-start/question-content-end;
}
as-question as-marks {
  grid-column: marks-start/marks-end;
}
as-question as-part {
  display: contents;
}
as-question as-part:before {
  counter-reset: subpart;
  counter-increment: part;
  grid-column: part-number-start/part-number-end;
  content: "(" counter(part, lower-alpha) ")";
  text-align: right;
}
as-question as-part > div.content > :not(as-subpart) {
  grid-column: part-content-start/part-content-end;
}
as-question as-part as-marks {
  color: red;
}
as-question as-subpart {
  display: contents;
}
as-question as-subpart:before {
  counter-increment: subpart;
  grid-column: subpart-number-start/subpart-number-end;
  content: "(" counter(subpart, lower-roman) ")";
  text-align: right;
}
as-question as-subpart > div.content * {
  grid-column: subpart-content-start/subpart-content-end;
}
as-question as-subpart as-marks {
  color: blue;
}
<div class='wrapper'>
  <as-question>
    <div class='content'>
      <p>This is some question content</p>
      <as-part>
        <as-marks>2</as-marks>
        <div class='content'>
          <p>Part: How can I not be pushed down?</p>
          <as-subpart>
            <as-marks>1</as-marks>
            <div class='content'>
              <p>Subpart</p>
            </div>
          </as-subpart>
          <as-subpart>
            <as-marks>1</as-marks>
            <div class='content'>
              <p>Subpart</p>
            </div>
          </as-subpart>
        </div>
      </as-part>
      <as-part>
        <as-marks>6</as-marks>
        <div class='content'>
          <p>Part</p>
          <as-subpart>
            <as-marks>4</as-marks>
            <div class='content'>
              <p>Subpart</p>
            </div>
          </as-subpart>
          <as-subpart>
            <as-marks>2</as-marks>
            <div class='content'>
              <p>Subpart</p>
            </div>
          </as-subpart>
        </div>
      </as-part>
    </div>
  </as-question>
</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

HTML and CSS for an off-canvas menu

Looking to create an off-canvas menu that smoothly pushes content out of view instead of cropping it. Additionally, I want to implement a feature that allows the menu to close when clicking outside of it. I found the code for the off-canvas menu on W3Scho ...

Sorting feature fails to function properly when used in combination with pagination and

<table> <thead> <tr> <th class="col-md-3" ng-click="sortDirection = !sortDirection">Creation Date</th> </tr> </thead> <tbody> <tr dir-paginate="item in items | filter:itemFilter | items ...

Utilizing the jQuery .wrap() method to encase the surrounding HTML

I am currently using the following jQuery code: jQuery( ".quantity" ).wrap( "<div class=\"engrave_button\"></div>" ) to wrap the quantity div with the engrave_button div. However, I need to include the ...

Implementing the decrement functionality within an onclick event handler for a variable

Can someone assist me with this issue? I am trying to use a variable ID in HTML to call a function on a JavaScript page. For example: (Minus button not functioning) <button class="minus-button quantity-button button" type="button" name="subtract" onc ...

The mouse pointer adjusts according to the event

I am working on an ajax request and I have implemented a feature where the cursor changes appearance. document.body.style.cursor = "wait"; This immediately shows the cursor as a spinning circle when the request starts. At the end of the request, I ch ...

Enhanced Interactivity: jQuery UI Dialog Button Transforms Position upon Mouse Hover

I am utilizing the jQuery UI dialog feature and implementing buttons using jQuery in the following manner: $("#151").dialog({ autoOpen: false, autoResize: true, buttons: { "OK": function ...

Activate animation while scrolling the page

I am using a progress bar with Bootstrap and HTML. Below is the code snippet: $(".progress-bar").each(function () { var progressBar = $(this); progressBar.animate({ width: progressBar.data('width') + '%' }, 1500); }); <body> & ...

How can screen readers be alerted about freshly loaded content through ajax?

Whenever a user clicks on a button, I want to add more content to the page. The new content will be visually clear, but how can I ensure that screen readers can easily access it? I've come across two best practices that suggest additional steps may b ...

Drag and Drop Feature using Angular with JQuery UI for Cloning Elements

I've been working on a web design project where I want to create a draggable user interface. https://i.sstatic.net/Be0Jk.png The goal is for users to click and drag different types of questions from the left side to the right side of the screen. Cu ...

Overlap caused by padding between two elements

I'm encountering an issue where adding padding to a block element is causing it to overlap with the padding of other elements. Below is the code snippet showcasing this problem. <section class="hero"> <h1>Studying REDEFIN ...

Alter the background of cards in real-time

I am unfamiliar with JavaScript, but I wish to utilize a function to alter the background color of multiple cards. function ChangeColorToGreen() { document.getElementById("ChangingCard").style.background = "green"; } function ChangeColorToPurple() { ...

Updating the Animation for Datepicker Closure

While using the date picker, I want it to match the width of the input text box. When closing the date picker, I prefer a smooth and single motion. However, after selecting a from and to date, the datepicker no longer closes smoothly. I have attempted sol ...

Real-time Broadcasts Straight to Your Web Browser

Feeling a bit frustrated with my current situation. I am eager to stream a live video broadcast to a web browser. At the moment, I am utilizing ffmpeg to stream a directshow live source as a webm stream to node.js, which then sends the stream to the http ...

Target the select element with a specific style applied, but restrict it to only be selected when nested within a div that shares the same style

Not quite sure about the effectiveness of the title, but here's what I'm attempting to accomplish. <div class="mystyle"> <select name="somename" id="somename"> <option value="Value1"> <option value="Value2" ...

When utilizing *NgIf, the button will be shown without the accompanying text being displayed

When trying to display either a confirm or cancel button based on a boolean set in my component.ts, I implemented the following code in my HTML: <mat-dialog-actions class="dialog-actions"> <button class="cancel-btn" ...

Is there a way to modify or update the CSS classes and overall styling in .gsp files within the Grails framework?

What is the best way to dynamically update a DOM element's class and styling in response to specific conditions or events occurring in a .gsp file? ...

Issue with Bootstrap navigation bar not displaying on iPad devices

Currently, I am working on creating a custom bootstrap menu that displays properly on an iPad screen size. I have implemented the standard navbar code from Bootstrap with a few tweaks. While it works well on smartphones and laptops, the issue arises when ...

difficulty with displaying the following image using jquery

I have referenced this site http://jsfiddle.net/8FMsH/1/ //html $(".rightArrow").on('click',function(){ imageClicked.closest('.images .os').next().find('img').trigger('click'); }); However, the code is not working ...

Ensure alignment of gradients between two divs, even if their widths vary

Among my collection of 10 inline divs, each one boasts a unique width and color gradient. While the 45-degree lines are uniform across all the divs, is there a way to ensure that these gradients match seamlessly? I've shared my CSS code snippet below ...

Unusual perspective of JSON with ng-jsoneditor in AngularJS

Currently, I have integrated ng-jsoneditor into my AngularJS application to display and format JSON data. I found guidance on how to implement this from both here and here. Here is the HTML code snippet: <div ng-jsoneditor="onLoad" ng-model="vm. ...