Tips for structuring a news thread with a staggered approach

On my Drupal 8 website, I have set up a newsfeed. How can I display the news items in staggered rows?

I would like the first item to align on the left and the second item to be on the right, repeating this pattern for all subsequent items. Currently, I am manually adding the class .right to achieve this layout, which is working fine.

However, given that I need to display a large number of blocks in the feed, how can I add this class automatically?

<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 home-page-footer">
            <div class="col-md-12 timelines">
              <div class="main-timeline">
                <div class="timeline">
                  <div class="timeline-icon">
                    <i class="fas fa-globe-americas"></i>
                  </div>
                  <div class="timeline-content">
                    <h3 class="title">Community</h3>
                    <p class="description">
                    By joining groups and sharing content within them, you can meet new people with similar interests and invite your friends. You also have the option to follow groups and shops.
                    </p>
                  </div>
                </div>
                <div class="timeline">
                  <div class="timeline-icon">
                    <i class="fas fa-thumbs-up"></i>
                  </div>
                  <div class="timeline-content right">
                    <h3 class="title">Simplicity</h3>
                    <p class="description">
                    S1BIOSE is user-friendly and accessible to everyone. It features responsive design, making it compatible with various devices (phones, tablets, e-readers, computers, and TVs) while its large buttons enhance touch screen usability.
                    </p>
                  </div>
                </div>
                <div class="timeline">
                  <div class="timeline-icon">
                    <i class="fas fa-cookie-bite"></i>
                  </div>
                  <div class="timeline-content">
                    <h3 class="title">Privacy-Conscious</h3>
                    <p class="description">
                    S1BIOSE is hosted by a French company on servers located in France and is registered with the National Commission for Information Technology and Civil Liberties (CNIL). Users can delete their accounts and posts at any time.
                    </p>
                  </div>
                </div>
              </div>
            </div>
          </div>

CSS:

.main-timeline .timeline-content {
    width: 45%;
    padding: 20px;
    border-radius: 5px;
    background: #ffffff;
    -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -moz-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -ms-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -o-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    box-shadow: 0 0 10px rgba(0,0,0,0.22);
}

.main-timeline .timeline-content:before {
    content: "";
    border-left: 7px solid #ffffff;
    border-top: 7px solid transparent;
    border-bottom: 7px solid transparent;
    position: absolute;
    left: 45%;
    top: 20px;
}

.main-timeline .timeline-content.right {
    float: right;
}

.main-timeline .timeline-content.right:before {
    content: "";
    right: 45%;
    left: inherit;
    border-left: 0;
    border-right: 7px solid #ffffff;
}

Manually adding the .right class to .timeline-content produces the desired result:

For automatic addition of the .right class to every even-numbered line when creating a view with Drupal:

To accomplish this in a JavaScript file, use the following code snippet:

$('.timelines').on('even', function () {
       $('timeline-content').addClass('right');
});

 $('.timeline:nth-child(even) .timeline-content').addClass('right');
.main-timeline {
    position: relative;
}

.main-timeline:before {
    z-index: -1;
    content: "";
    width: 3px;
    height: 100%;
    background: #ffffff;
    -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -moz-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -ms-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -o-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    box-shadow: 0 0 10px rgba(0,0,0,0.22);
    position: absolute;
    top: 0;
    left: 49.9%;
}

.main-timeline .timeline {
    margin-top: 50px;
    position: relative;
}

.main-timeline .timeline:before,
.main-timeline .timeline:after {
    content: "";
    display: block;
    width: 100%;
    clear: both;
}

.main-timeline .timeline-icon {
    width: 52px;
    height: 52px;
    border-radius: 50%;
    background: #ffffff;
    -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -moz-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -ms-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -o-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    box-shadow: 0 0 10px rgba(0,0,0,0.22);
    overflow: hidden;
    margin-left: -26px;
    position: absolute;
    top: 0;
    left: 50%;
    text-align: center;
}

.main-timeline .timeline-icon img {
    width: 50px;
    height: 50px;
}

.main-timeline .timeline-content {
    width: 45%;
    padding: 20px;
    border-radius: 5px;
    background: #ffffff;
    -webkit-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -moz-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -ms-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    -o-box-shadow: 0 0 10px rgba(0,0,0,0.22);
    box-shadow: 0 0 10px rgba(0,0,0,0.22);
}

.main-timeline .timeline-content:before {
    content: "";
    border-left: 7px solid #ffffff;
    border-top: 7px solid transparent;
    border-bottom: 7px solid transparent;
    position: absolute;
    left: 45%;
    top: 20px;
}

.main-timeline .timeline-content.right {
    float: right;
}

.main-timeline .timeline-content.right:before {
    content: "";
    right: 45%;
    left: inherit;
    border-left: 0;
    border-right: 7px solid #ffffff;
}

.timeline:nth-child(even) .timeline-content {
    float: right;
}

.timeline:nth-child(even) .timeline-content:before {
    content: "";
    right: 45%;
    left: inherit;
    border-left: 0;
    border-right: 7px solid #ffffff;
}

.main-timeline .timeline-title {
    color: #000000;
    padding: 10px;
    background: #ffffff;
    border-bottom: 1px solid #cccccc;
    border-radius: 3px 3px 0 0;
    margin: -20px -20px 0px -20px;
}

.main-timeline .timeline-title h3 {
    font-size: 30px;
    font-weight: 300;
    margin-top: 0;
}

.main-timeline .timeline-title h6 {
    margin-bottom: 0;
}

.main-timeline .timeline-description {
    margin-top: 10px;
}

@media only screen and (max-width: 990px) {
    .main-timeline .timeline-title h3 {
        font-size: 25px;
    }
    .main-timeline .timeline-content::before {
        top: 16px;
    }
}

@media only screen and (max-width: 767px) {
    .main-timeline {
        margin-left: 20px;
    }
    .main-timeline:before {
        left: 0;
    }
    .main-timeline .timeline-content {
        width: 90%;
        float: right;
    }
    .main-timeline .timeline-content:before,
    .main-timeline .timeline-content.right:before {
        left: 10%;
        right: inherit;
        margin-left: -6px;
        border-left: 0;
        border-right: 7px solid #ffffff;
    }
    .main-timeline .timeline-icon {
        left: 0;
    }
}

@media only screen and (max-width: 479px) {
    .main-timeline .timeline-content {
        width: 85%;
    }
    .main-timeline .timeline-content:before,
    .main-timeline .timeline-content.right:before {
        left: 15%;
    }
    .main-timeline .timeline-title h3 {
        font-size: 20px;
    }
    .main-timeline .timeline-content:before {
        top: 13px;
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 home-page-footer">
            <div class="col-md-12 timelines">
              <div class="main-timeline">
                <div class="views-element-container form-group"><div class="view view-timeline-public view-id-timeline_public view-display-id-block_1 js-view-dom-id-38d0b8b38b7d1f7be5c3ba53e63939fd9979deb1ce7bd918a170a79832785389">
  
    
      
      <div class="view-content">
      <div data-drupal-views-infinite-scroll-content-wrapper="" class="views-infinite-scroll-content-wrapper clearfix form-group">    <div class="views-row"><div>
  <div class="timeline">
   <div class="timeline-icon">
      https://www.s1biose.com/sites/default/files/styles/thumbnail/public/2018-02/linux_circuit_board_penguin_avatar_by_duradcell-d6gzwwu.jpg?itok=JnvROb1j
   </div>
   <div class="timeline-content">
      <div class="timeline-title">
         <h3><a href="/discussion/test-56">test 56</a></h3>
         <h6>jeu, 06/09/2018 - 12:57</h6>
      </div>
      <p class="timeline-description">
         New content (Discussion)<br>
         created by <a href="/user/1">administrator</a><br>
         in the group [message:field_group_reference:entity:title]
      </p>
   </div>
</div>
</div>
</div>
    <div class="views-row"><div>
  <div class="timeline">
   <div class="timeline-icon">
      https://www.s1biose.com/sites/default/files/styles/thumbnail/public/2018-02/linux_circuit_board_penguin_avatar_by_duradcell-d6gzwwu.jpg?itok=JnvROb1j
   </div>
   <div class="timeline-content">
      <div class="timeline-title">
         <h3><a href="/discussion/test-77">test 77</a></h3>
         <h6>jeu, 06/09/2018 - 12:56</h6>
      </div>
      <p class="timeline-description">
         New content (Discussion)<br>
         created by <a href="/user/1">administrator</a><br>
         in the group [message:field_group_reference:entity:title]
      </p>
   </div>
</div>
</div>
</div>
    <div class="views-row"><div>
  <div class="timeline">
   <div class="timeline-icon">
      https://www.s1biose.com/sites/default/files/styles/thumbnail/public/2018-02/linux_circuit_board_penguin_avatar_by_duradcell-d6gzwwu.jpg?itok=JnvROb1j
   </div>
   <div class="timeline-content">
      <div class="timeline-title">
         <h3><a href="/discussion/test-55">test 55</a></h3>
         <h6>jeu, 06/09/2018 - 12:56</h6>
      </div>
      <p class="timeline-description">
         New content (Discussion)<br>
         created by <a href="/user/1">administrator</a><br>
         in the group [message:field_group_reference:entity:title]
      </p>
   </div>
</div>
</div>
</div>
    <div class="views-row"><div>
  <div class="timeline">
   <div class="timeline-icon">
      https://www.s1biose.com/sites/default/files/styles/thumbnail/public/2018-02/linux_circuit_board_penguin_avatar_by_duradcell-d6gzwwu.jpg?itok=JnvROb1j
   </div>
   <div class="timeline-content">
      <div class="timeline-title">
         <h3><a href="/discussion/test-6">test 6</a></h3>
         <h6>jeu, 06/09/2018 - 12:08</h6>
      </div>
      <p class="timeline-description">
         New content (Discussion)<br>
         created by <a href="/user/1">administrator</a><br>
         in the group [message:field_group_reference:entity:title]
      </p>
   </div>
</div>
</div>
</div>
    <div class="views-row"><div>
  <div class="timeline">
   <div class="timeline-icon">
      [message:author:user_picture:thumbnail]
   </div>
   <div class="timeline-content">
      <div class="timeline-title">
         <h3><a href="/user/11569">test</a></h3>
         <h6>jeu, 06/09/2018 - 01:18</h6>
      </div>
      <p class="timeline-description">
         Just signed up
      </p>
   </div>
</div>
</div>
</div>
    </div>
  
      
<ul class="js-pager__items pager" data-drupal-views-infinite-scroll-pager="">
  <li class="pager__item">
    <a class="button" href="/node?page=1" title="Go to next page" rel="next">Show More</a>
  </li>
</ul>

          </div>
</div>

              </div>
            </div>
          </div>

Answer №1

If you want to include a class in the HTML output of a view, you can achieve this by using a custom template.

To do this, simply copy the default twig file template

core/themes/classy/templates/views/views-view-XXXX.html.twig
to your theme folder and make your changes there.

For more information, you can refer to this link, which provides detailed steps on how to customize Drupal views rendering.

If you're not familiar with Drupal or prefer a simpler solution based on your HTML structure, you can also use CSS:

.view-content .views-row:nth-child(even) .timeline .timeline-content {
       background: red;  // adjust the properties as needed
}

By utilizing the :nth-child() selector with even or odd values, you can target specific elements for styling.

If adding a class directly to the element is necessary, you can accomplish this with jQuery:

$('.view-content .views-row:nth-child(even) .timeline .timeline-content').addClass('right');

You can also check out a codepen example showcasing both approaches at this link. In this demo, CSS sets the background color to red, while JavaScript adds the 'right' class with a blue border to the timeline-content element within even timeline parent.

I hope this information proves helpful!

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

The useSelector from @reduxjs/toolkit in Next.js is returning an undefined value

Utilizing js and @reduxjs/toolkit in my current project has resulted in an issue where the useSelector method is returning undefined values when trying to access data from the store. Below is a snippet of my reducer file: import { createSlice } from "@red ...

Flexible layout design for mobile devices

Check out how my desktop page looks: Desktop version If you want to see how it should appear on mobile, click here: Mobile Version This is the HTML/CSS code for the desktop version, and everything seems to be working fine. .skills { width: 80%; ba ...

Styling an unordered list with CSS in HTML is a powerful

I am working with an unordered list where each list element contains two spans: span A and span B. My goal is to style these elements so that they are displayed horizontally on the screen, with span A above span B in each set. Example: spanAItem1 sp ...

I am encountering an issue where the nested loop in Angular TypeScript is failing to return

I am facing an issue with my nested loop inside a function. The problem is that it is only returning the default value of false, instead of the value calculated within the loop. Can someone please point out what I might be doing incorrectly? Provided belo ...

The uncertainty surrounding the usage of checkboxes in D3.js

I am faced with the challenge of adding checkboxes to multiple groups within an SVG, each containing a circle and text element. I have attempted to accomplish this by using D3 to append foreignObject tags and then add checkboxes to each group. The code I h ...

React input value doesn't get updated on onChange event causing the input

Currently, I'm working on a React application that requires a table with inputs in each row. To achieve this, I am utilizing Material-UI and Formik. However, I've encountered a bug where input fields lose focus whenever I type something into them ...

jQuery - Endless paging

My attempt at implementing infinite scrolling on my page seems to have hit a snag. Instead of triggering at the bottom of the page, it's activating when I scroll back to the top. Can anyone shed some light on what might be causing this issue? $(windo ...

Safari causing issues with textures in Three.js CanvasRenderer

I am currently working on a Three.js based sample project that will serve as the foundation for a larger project. The project involves a plane with a texture which orbits a center point. The plane is attached to the center point and then the center point i ...

Where is the first next() call's argument located?

I'm facing an issue with a simple generator function function *generate(arg) { console.log(arg) for(let i = 0; i < 3;i++) { console.log(yield i); } } After initializing the generator, I attempted to print values in the console: var gen ...

What is the reason behind Q.js promises becoming asynchronous once they have been resolved?

Upon encountering the following code snippet: var deferred = Q.defer(); deferred.resolve(); var a = deferred.promise.then(function() { console.log(1); }); console.log(2); I am puzzled as to why I am seeing 2, then 1 in the console. Although I ...

Edit the settings for the dual-axis line chart's parameters

After countless hours of scouring the Internet and numerous attempts, I have come to the decision to seek help by posting my issue on this forum. I must confess, I am not the best developer. My approach usually involves finding pre-existing code that I ca ...

Implement a feature in JS/HTML where clicking on a button shifts a specific section of a row from one table to another while simultaneously deleting the remaining

I am facing an issue with two tables - addFriends and existingFriends. The addFriends table contains a button in the fourth column, which, upon clicking, should delete the corresponding row from that table and add it to the existingFriends table. Currentl ...

Determining the victorious player in a game of Blackjack

After the player clicks "stand" in my blackjack game, my program checks for a winner. I am using AJAX to determine if there is a winner. If there is a winner, an alert will display their name. Otherwise, the dealer will proceed with making their move. Any ...

I'm having an issue where my footer is getting cut off when I resize the browser and start side scrolling. Can

I designed a webpage with a footer that contains another div holding centered content. The footer is supposed to span the entire width, while the inner content div is set to 960px with a margin auto to center it. <footer> <div class="footer-in ...

Issue with Custom Dropdown input not triggering blur event

I've been working on a custom dropup component and have encountered some strange issues with it. The main problem is the blur event not firing when clicking outside of the input field. My goal is to hide the options elements on blur, reset the compon ...

Passing arguments to the callback function in React: a comprehensive guide

Within my react component, I have a collection of elements that I want to make clickable. When clicked, I trigger an external function and pass the item ID as an argument: render () { return ( <ul> {this.props.items.map(item => ( ...

Aligning a table at the center of another table

Frustration has been brewing within me all week as I grapple with the task of sending out an important emailer soon. The challenge lies in aligning these product images next to their descriptions at the center, a feat that seems impossible to achieve withi ...

I am in search of a method to rephrase the content while minimizing redundancy

I am looking to improve the code for handling two different conditions in the UI. Can someone suggest a better way to rewrite it? <i *ngIf="measures.length > 0"> <ul *ngFor="let m of measures"> <io-data-selection-row [text] ...

Error: The URI you are trying to access is restricted and access has been denied

I'm facing an issue with my HTML file that contains multiple d3-graphs embedded directly within script tags. When I try to move one of the graphs to an external JavaScript file, I receive the following error message: "NS_ERROR_DOM_BAD_URI: Access to r ...

Unlocking the secrets of obtaining post values using Body-parser in your Express Node.js application

Currently, I am utilizing Express version 4.11.1 and Body-parser version 1.11.0 in my project. However, upon running the code snippet below, I encountered the following output: I am seeking suggestions on how to retrieve the form value. Output {} serve ...