Ways to adjust the position of a DIV based on its index value

I'm currently working on a unique project that involves creating a triangular grid using HTML and CSS. The challenge I am facing is offsetting each triangle in the grid to the left by increasing amounts so they fit seamlessly next to one another. Right now, I am using JavaScript to achieve this by setting the offset based on the triangle's index within the parent container. However, it feels like a workaround and I am exploring if there is a way to accomplish this purely with CSS. I wonder if there might be a CSS feature that allows me to access each triangle div’s index or if there is an alternative method in CSS to achieve the same result.

let triangleRows = [...document.getElementsByClassName('triangle-row')]

triangleRows.forEach(row => {
  let children = [...row.children]
  // set each triangle's --tri-index variable to its index
  children.forEach((tri, idx) => tri.style.setProperty('--tri-index', idx))
})
:root {
  --tri-width: 5rem;
  --tri-ratio: 0.86603;
  --offset: -2.25rem
}

.triangle-row {
  display: flex;
  margin-top: 0.2rem;
}

.triangle {
  position: relative;
  height: calc(var(--tri-width) * var(--tri-ratio));
  width: var(--tri-width);
  left: calc(var(--offset) * var(--tri-index));
  background-color: red;
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

.triangle:hover {
  background-color: yellow;
}

.flipped {
  clip-path: polygon(0% 0%, 50% 100%, 100% 0%);
}
<div class="triangle-row">
  <div class="triangle"></div>
  <div class="triangle flipped"></div>
  <div class="triangle"></div>
  <div class="triangle flipped"></div>
  <div class="triangle"></div>
</div>
<div class="triangle-row">
  <div class="triangle flipped"></div>
  <div class="triangle"></div>
  <div class="triangle flipped"></div>
  <div class="triangle"></div>
  <div class="triangle flipped"></div>
</div>

Answer №1

By incorporating a negative margin, I was able to achieve the same outcome without the triangles shifting further to the left.

:root {
  --tri-width: 5rem;
  --tri-ratio: 0.86603;
  --offset: -2.25rem
}

.triangle-row {
  display: flex;
  margin-top: 0.2rem;
}

.triangle {
  position: relative;
  height: calc(var(--tri-width) * var(--tri-ratio));
  width: var(--tri-width);
  margin-left: var(--offset); /* add the offset */
  background-color: red;
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
.triangle:first-child{
  margin-left: 0;
}

.triangle:hover {
  background-color: yellow;
}

.flipped {
  clip-path: polygon(0% 0%, 50% 100%, 100% 0%);
}
<div class="triangle-row">
  <div class="triangle"></div>
  <div class="triangle flipped"></div>
  <div class="triangle"></div>
  <div class="triangle flipped"></div>
  <div class="triangle"></div>
</div>
<div class="triangle-row">
  <div class="triangle flipped"></div>
  <div class="triangle"></div>
  <div class="triangle flipped"></div>
  <div class="triangle"></div>
  <div class="triangle flipped"></div>
</div>

Edit: Following @Bryce Howitson's suggestion, I have refined the CSS and eliminated the need for alternating "flipped" classes. This allows for easy addition of more triangles or rows of triangles.

:root {
  --tri-width: 5rem;
  --tri-ratio: 0.86603;
  --offset: -2.25rem
}
.triangle-row {
  display: flex;
  margin-top: 0.2rem;
}

.triangle {
  position: relative;
  height: calc(var(--tri-width) * var(--tri-ratio));
  width: var(--tri-width);
  margin-left: var(--offset); /* add the offset */
  background-color: red;
}

.triangle:hover {
  background-color: yellow;
}

.triangle:first-child {
  margin-left: 0;
}

.triangle-row:nth-child(odd) .triangle:nth-child(odd),
.triangle-row:nth-child(even) .triangle:nth-child(even) {
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

.triangle-row:nth-child(even) .triangle:nth-child(odd),
.triangle-row:nth-child(odd) .triangle:nth-child(even){
  clip-path: polygon(0% 0%, 50% 100%, 100% 0%);
}
<div class="triangle-row">
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
</div>
<div class="triangle-row">
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
  <div class="triangle"></div>
</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

Interactive navigation with jQuery

I am currently utilizing a jQuery menu script that enhances the navigation structure on my website: (function($) { $.fn.blowfish = function() { // concealing the original ul dom tree $(this).hide(); // constructing a container from top-l ...

Customizing Mat Horizontal Stepper Icons with Unique Background Colors in Angular Material

I'm having trouble customizing the colors of the icons In my mat-horizontal-stepper, I have five mat-steps (Part A, Part B ... Part E), each needing a different color based on certain business rules. While I can change the color for all steps or the ...

The chart appears oversized in the vue js. How can I make it smaller in size?

I recently integrated a line chart from Chart JS into my Vue.js project, but the chart is taking up too much space on my webpage. I'm looking for ways to make it appear smaller and more compact. This is my first time working with charts in Vue.js, so ...

Regularly send requests to an Express server using the $.get function

Operating an Express server with a time generator to send generated time data to the client page gtm.hbs. How can I implement regular polling of the server from the client using Ajax? Displayed below is the server-side code located in \routes\ge ...

Is it possible in Javascript to verify if a different script has been triggered?

I recently created a pop-out menu for a website using HTML and Javascript. The menu currently has a button that opens a div container with a close button inside it. While the buttons are functioning properly in hiding the div, the elements within the div d ...

Load a distinct JSP file from the sidebar in JSP

I have an index.jsp file containing a sidebar: <div id="sidebar"> <li ><a href="create">Create</a></li> <li ><a href="view">View</a></li> <li ><a href="Delete">Delete</a></li> & ...

New example of how to use the "useSession" syntax in Next Auth

Currently, I am delving into the next-auth documentation and feeling perplexed by the syntax used in the useSession hook. The way it's showcased in the documentation is as follows: const { data: session, status } = useSession() My confusion stems f ...

Refresh the JavaScript graph with new data from the AJAX request

Seeking assistance in updating my javascript chart data using ajax data retrieved from a database. The specific chart being referenced is an apex chart. After submitting a form via ajax, the returned result is as follows: type: "POST",crossDomain ...

Combine two or more Firebase Observables

Currently, I am working on creating an Observable using FirebaseObjectObservable. However, before I can accomplish this, I need to query a Firebase list to obtain the key IDs required for the FirebaseObjectObservable. The structure of my data is as follow ...

Styling the select dropdown border in Google Chrome

I am encountering an issue with styling HTML select options in Chrome. Despite successfully applying borders to each option in Firefox, I cannot get it to work in Chrome. Can anyone advise on how this can be achieved? <select id="sortingOptions" class= ...

What are the steps to transforming a regular expression into a dynamic format?

I've developed a powerful regex that locates specific text within a lengthy string without spaces. Now I'm attempting to utilize it dynamically to search for various words, but I can't seem to make it function as intended. Check out my rege ...

Ways to integrate a component within a custom component in the React framework

I am looking to dynamically change the body content, how can I achieve this? import React from 'react' // import { Link } from 'react-router-dom' export default function ProjectTemplate(props) { const Css= { "--backgr ...

Expanding the use of tagged template literals for passing additional arguments

Currently, I am utilizing styled-components and creating components through their tagged template literal syntax like this: const Button = styled.button` background-color: papayawhip; border-radius: 3px; color: palevioletred; ` In a specific scenar ...

Text that is superimposed onto an image

Struggling to implement a hovering text over an image? I attempted to follow a tutorial, but couldn't adapt it to my project. While I managed to create a fixed overlay, I aim for a responsive solution that adjusts with resolution changes. My goal is t ...

What is the best way to transform an array of objects into an array that contains a distinct identifier in JavaScript?

I am currently working with an array of objects structured like this: { "data": [ { "id": 1, "from": "2022-08-01", "to": "2022-08-05", & ...

Is there a way to ensure consistent heights for various elements within a column, even if their heights are

Currently, I am utilizing the flex property to create uniform columns and vh to ensure they have the same height. This setup is functioning properly, but within each column, there could be a varying number of items. I am interested in having the elements w ...

Mocking a named class-export in TypeScript using Jest

I have a node module that exports several classes, including one called Client, which I utilize to create clients with various APIs as methods. I'm currently attempting to test my module, which has a dependency on this node module, using Jest. Howeve ...

Modifying the onclick function for a bootstrap glyphicon

How can I swap the .glyphicon-menu-down to glyphicon-menu-up when a user clicks on a link? Currently, it's not working as expected. Could there be an issue with my jQuery implementation? Markup <a data-toggle="collapse" data-parent="#accordion" h ...

Apply a border to the div that has been selected

I have a tool for storing information and I am using *ngFor to display each instance in a line. Is there a way to add a border when clicking on a line? The border should only appear on the clicked line, disappearing from the previous one if another line i ...

Detecting Changes in Angular Only Works Once when Dealing with File Input Fields

Issue arises with the file input field as it only allows uploading one file at a time, which needs to be modified. Uploading a single file works fine. However, upon attempting to upload multiple files, it appears that the "change" handler method is not tr ...