Buttons positioned relative to the container have been corrected

I am looking to implement navigation buttons that will remain fixed vertically within a long table as the user scrolls through it. These buttons are intended to facilitate horizontal scrolling within the table, ensuring they stay contained within the table itself. When using 'fixed' positioning, the buttons break out of the table and become tied to the viewport. Adding translatez:(0) to the parent container causes the buttons to no longer move along with the center of the page.

document.addEventListener('DOMContentLoaded', function() {
  const tableContainer = document.getElementById('table-container');
  const scrollLeft = document.getElementById('scroll-left');
  const scrollRight = document.getElementById('scroll-right');

  let scrollInterval;

  function updateArrows() {
    scrollLeft.style.display = tableContainer.scrollLeft > 0 ? 'block' : 'none';
    scrollRight.style.display = (tableContainer.scrollWidth > tableContainer.clientWidth) &&
      (tableContainer.scrollLeft < tableContainer.scrollWidth - tableContainer.clientWidth) ? 'block' : 'none';
  }

  function startScrolling(direction) {
    stopScrolling(); // Ensure no other scrolling is active
    scrollInterval = setInterval(function() {
      tableContainer.scrollBy({
        left: direction === 'left' ? -10 : 10,
        behavior: 'smooth'
      });
    }, 50); // Adjust scroll speed by changing the interval time or the scroll amount
  }

  function stopScrolling() {
    clearInterval(scrollInterval);
  }

  scrollLeft.addEventListener('mousedown', function() {
    startScrolling('left');
  });

  scrollRight.addEventListener('mousedown', function() {
    startScrolling('right');
  });

  document.addEventListener('mouseup', stopScrolling);
  document.addEventListener('mouseleave', stopScrolling);

  tableContainer.addEventListener('scroll', updateArrows);

  // Initial check
  updateArrows();
});
.scroll-container {
  position: relative;
  display: flex;
  align-items: center;
  width: fit-content;
  margin: 0 auto;
  /* transform: translateZ(0);*/
}

.table-container {
  overflow-x: auto;
  white-space: nowrap;
  width: 300px;
  /* Adjust based on your design */
  border: 1px solid #ddd;
  position: relative;
  /* Needed for absolute positioning of arrows */
}

.scroll-arrow {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  background-color: #f1f1f1;
  border: 1px solid #ddd;
  padding: 5px;
  cursor: pointer;
  display: none;
  z-index: 1;
}

#scroll-left {
  left: 0;
}

#scroll-right {
  right: 0;
}


/* Table styling */

table {
  border-collapse: collapse;
}

th,
td {
  border: 1px solid #ddd;
  padding: 8px;
}
<p>Unique text goes here.</p>

Answer №1

I trust that the solution provided above will be suitable for your needs (Feel free to run the Snippet). Hopefully, it aligns with what you were looking for.

This is the process I followed:

  • Exclusion of display flex from the scroll container
  • .scroll-arrow - adjusted position to absolute and added width: 30px;
  • #scroll-left {left: -50px;}
  • #scroll-right {right: -50px;}

For further clarity, please refer below.

document.addEventListener('DOMContentLoaded', function() {
  const tableContainer = document.getElementById('table-container');
  const scrollLeft = document.getElementById('scroll-left');
  const scrollRight = document.getElementById('scroll-right');

  let scrollInterval;

  function updateArrows() {
    scrollLeft.style.display = tableContainer.scrollLeft > 0 ? 'block' : 'none';
    scrollRight.style.display = (tableContainer.scrollWidth > tableContainer.clientWidth) &&
      (tableContainer.scrollLeft < tableContainer.scrollWidth - tableContainer.clientWidth) ? 'block' : 'none';
  }

  function startScrolling(direction) {
    stopScrolling(); // Ensure no other scrolling is active
    scrollInterval = setInterval(function() {
      tableContainer.scrollBy({
        left: direction === 'left' ? -10 : 10,
        behavior: 'smooth'
      });
    }, 50); // Adjust scroll speed by changing the interval time or the scroll amount
  }

  function stopScrolling() {
    clearInterval(scrollInterval);
  }

  scrollLeft.addEventListener('mousedown', function() {
    startScrolling('left');
  });

  scrollRight.addEventListener('mousedown', function() {
    startScrolling('right');
  });

  document.addEventListener('mouseup', stopScrolling);
  document.addEventListener('mouseleave', stopScrolling);

  tableContainer.addEventListener('scroll', updateArrows);

  // Initial check
  updateArrows();
});
.scroll-container {
  position: relative;
  /*display: flex;
  align-items: center;*/
  width: fit-content;
  margin: 0 auto;
  /* transform: translateZ(0);*/
}

.table-container {
  overflow-x: auto;
  white-space: nowrap;
  width: 300px;
  /* Adjust based on your design */
  border: 1px solid #ddd;
  position: relative;
  /* Needed for absolute positioning of arrows */
}

.scroll-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background-color: #f1f1f1;
  border: 1px solid #ddd;
  padding: 5px;
  cursor: pointer;
  display: none;
  z-index: 1;
  width:30px;
}

#scroll-left {
  left: -50px;
}

#scroll-right {
  right: -50px;
}

table {
  border-collapse: collapse;
}

th,
td {
  border: 1px solid #ddd;
  padding: 8px;
}
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum exercitationem dolores animi quasi odit deserunt, reprehenderit facere veritatis natus. Iusto error sunt cumque delectus rem obcaecati et temporibus cum ea?</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum exercitationem dolores animi quasi odit deserunt, reprehenderit facere veritatis natus. Iusto error sunt cumque delectus rem obcaecati et temporibus cum ea?</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum exercitationem dolores animi quasi odit deserunt, reprehenderit facere veritatis natus. Iusto error sunt cumque delectus rem obcaecati et temporibus cum ea?</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum exercitationem dolores animi quasi odit deserunt, reprehenderit facere veritatis natus. Iusto error sunt cumque delectus rem obcaecati et temporibus cum ea?</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum exercitationem dolores animi quasi odit deserunt, reprehenderit facere veritatis natus. Iusto error sunt cumque delectus rem obcaecati et temporibus cum ea?</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum exercitationem dolores animi quasi odit deserunt, reprehenderit facere veritatis natus. Iusto error sunt cumque delectus rem obcaecati et temporibus cum ea?</p>
<div class="scroll-container">
  <button id="scroll-left" class="scroll-arrow">&lt;</button>
  <div id="table-container" class="table-container">
    <table>
      <thead>
        <tr>
          <th>Header 1</th>
          <th>Header 2</th>
          <th>Header 3</th>
          <th>Header 4</th>
          <th>Header 5</th>
          <th>Header 6</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Data 1</td>
          <td>Data 2</td>
          <td>Data 3</td>
          <td>Data 4</td>
          <td>Data 5</td>
          <td>Data 6</td>
        </tr>
        <tr>
          <td>Data 1</td>
          <td>Data 2</td>
          <td>Data 3</td>
          <td>Data 4</td>
          <td>Data 5</td>
          <td>Data 6</td>
        </tr>
        <!-- More rows as needed -->
      </tbody>
    </table>
  </div>
  <button id="scroll-right" class="scroll-arrow">&gt;</button>
</div>

Many thanks

Answer №2

Are you enjoying this demonstration? If so, make sure to include position: absolute in the .scroll-arrow class.

document.addEventListener('DOMContentLoaded', function() {
  const tableContainer = document.getElementById('table-container');
  const scrollLeft = document.getElementById('scroll-left');
  const scrollRight = document.getElementById('scroll-right');

  let scrollInterval;

  function updateArrows() {
    scrollLeft.style.display = tableContainer.scrollLeft > 0 ? 'block' : 'none';
    scrollRight.style.display = (tableContainer.scrollWidth > tableContainer.clientWidth) &&
      (tableContainer.scrollLeft < tableContainer.scrollWidth - tableContainer.clientWidth) ? 'block' : 'none';
  }

  function startScrolling(direction) {
    stopScrolling(); // Ensure no other scrolling is active
    scrollInterval = setInterval(function() {
      tableContainer.scrollBy({
        left: direction === 'left' ? -10 : 10,
        behavior: 'smooth'
      });
    }, 50); // Adjust scroll speed by changing the interval time or the scroll amount
  }

  function stopScrolling() {
    clearInterval(scrollInterval);
  }

  scrollLeft.addEventListener('mousedown', function() {
    startScrolling('left');
  });

  scrollRight.addEventListener('mousedown', function() {
    startScrolling('right');
  });

  document.addEventListener('mouseup', stopScrolling);
  document.addEventListener('mouseleave', stopScrolling);

  tableContainer.addEventListener('scroll', updateArrows);

  // Initial check
  updateArrows();
});
.scroll-container {
  position: relative;
  display: flex;
  align-items: center;
  width: fit-content;
  margin: 0 auto;
}

.table-container {
  overflow-x: auto;
  white-space: nowrap;
  width: 300px;
  border: 1px solid #ddd;
  position: relative;
}

.scroll-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background-color: #f1f1f1;
  border: 1px solid #ddd;
  padding: 5px;
  cursor: pointer;
  display: none;
  z-index: 1;
}

#scroll-left {
  left: 0;
}

#scroll-right {
  right: 0;
}

table {
  border-collapse: collapse;
}

th,
td {
  border: 1px solid #ddd;
  padding: 8px;
}
<p>Enjoying the interactive demo and code snippet? Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
<p>Explore more functionalities and adjustments to this design!</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum exercitationem dolores animi quasi odit deserunt...</p>
<p>More lorem ipsum text for a dynamic and engaging experience!</p>
<p>Try out different settings and see how it affects the layout and functionality of the table container.</p>

Answer №3

To enhance @Akshay's response, I propose setting a specific max-height for the .table-container element that is less than the viewport height. This will enable vertical and horizontal scrolling, ensuring that the arrows remain visible as the table moves beneath them.

document.addEventListener('DOMContentLoaded', function() {
  const tableContainer = document.getElementById('table-container');
  const scrollLeft = document.getElementById('scroll-left');
  const scrollRight = document.getElementById('scroll-right');

  let scrollInterval;

  function updateArrows() {
    scrollLeft.style.display = tableContainer.scrollLeft > 0 ? 'block' : 'none';
    scrollRight.style.display = (tableContainer.scrollWidth > tableContainer.clientWidth) &&
      (tableContainer.scrollLeft < tableContainer.scrollWidth - tableContainer.clientWidth) ? 'block' : 'none';
  }

  function startScrolling(direction) {
    stopScrolling(); // Ensure no other scrolling is active
    scrollInterval = setInterval(function() {
      tableContainer.scrollBy({
        left: direction === 'left' ? -10 : 10,
        behavior: 'smooth'
      });
    }, 50); // Adjust scroll speed by changing the interval time or the scroll amount
  }

  function stopScrolling() {
    clearInterval(scrollInterval);
  }

  scrollLeft.addEventListener('mousedown', function() {
    startScrolling('left');
  });

  scrollRight.addEventListener('mousedown', function() {
    startScrolling('right');
  });

  document.addEventListener('mouseup', stopScrolling);
  document.addEventListener('mouseleave', stopScrolling);

  tableContainer.addEventListener('scroll', updateArrows);

  // Initial check
  updateArrows();
});
.scroll-container {
  position: relative;
  display: flex;
  align-items: center;
  width: fit-content;
  margin: 0 auto;
}

.table-container {
  overflow: auto;
  white-space: nowrap;
  width: 300px;
  border: 1px solid #ddd;
  position: relative;
  max-height: 90svh; /* Modify based on design */
}

.scroll-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background-color: #f1f1f1;
  border: 1px solid #ddd;
  padding: 5px;
  cursor: pointer;
  display: none;
  z-index: 1;
}

#scroll-left {
  left: 0;
}

#scroll-right {
  right: 0;
}

table {
  border-collapse: collapse;
}

th,
td {
  border: 1px solid #ddd;
  padding: 8px;
}
<p>Unique content goes here.</p>

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

Enhance the performance of React code by refactoring it

Having recently started coding in React for a new organization, I find that the code in my component has grown lengthy and the submithandler method is causing multiple array iterations. Is there a way to refactor the code for better performance? The data t ...

Intercepting the K-pager navigation with a pop-up modal for user confirmation before switching to a different page

Scenario Currently, I have developed a WebApp using kendo, bootstrap, and backbone. One of the key features is a grid that showcases data pulled from a database. This grid has a data source binding with serverPaging enabled. Data Source Configuration al ...

Display a dynamic indicator on the map

I am working on a project where I need to make a marker move smoothly on the map as a vehicle travels along the road. There are two sets of latLng values, and I want the marker to smoothly transition between these two points until the next set of coordina ...

What causes the navbar-brand to be hidden on Chrome mobile browsers?

I recently completed building my website at emdashr.com and have been adjusting the mobile views. However, I'm facing an issue where the navbar-brand disappears when viewing the site on mobile Chrome or desktop Chrome with a small viewport. Interestin ...

React: Ever wonder why changing the state directly ends up putting the component in such a peculiar state?

Before we proceed, I want to clarify that I am aware that mutating the state is not a recommended practice. However, I am curious to explore the potential consequences of directly mutating the state. Let's consider a simple todo app that stores todo ...

Strange Phenomenon: Website Appears Enlarged When Accessed through Server

Similar Question: Why does my website appear smaller on a live server than when deployed locally? After reviewing the answer to the similar question linked above, I still found myself facing the same issue with no resolution. My problem is that the webpa ...

The Axios wrapper function is returning an undefined value when using MockReturnValue

I've been working on testing my componentDidMount function to ensure that the axiosRequest it calls returns an array. However, no matter how I try to mock the axiosRequest function, it always seems to return undefined. What am I missing? Here's ...

Guide for adding multiple markers on a Google map

Currently, I am facing a challenge with plotting multiple markers on a Google map and need some assistance. The longitude and latitude of the locations are extracted from JSON data obtained through an AJAX API call. I have been referring to a particular p ...

Replicate the [condition] within the range of [colA] and [colB] using sequelize

I need assistance in converting the following MSSQL operation to Sequelize. Our table includes valid_from and valid_to columns, and I only want to retrieve records that fall within today's date range. My goal is to use either the .findByPK() or .find ...

Unable to establish a connection with the browser using Socket.IO Spring server, but it works successfully when connecting with

After developing a Spring Boot Application with a SocketIoServer Endpoint, I encountered an issue where the server worked perfectly when tested in a Node.js client environment, but did not respond in Chrome or Edge browsers (haven't tested others). T ...

What's the best way to alter the style of an element within a <div /> using JavaScript?

Looking at my index.html, I see the following code: <div id="mydiv"> Text inside div <h1> Header inside div </h1> </div> <h1> Header outside div </h1> My style.css file is defined like this: #mydi ...

Consistent form elements on both Mac and PC browsers

Seeking the most effective method to ensure consistent form elements appearance on all browsers, whether on PC or Mac. It seems like a basic question that I should have already known the answer to, but oddly enough, I'm struggling to figure it out. I ...

Troubleshooting jQuery Div Separation Problem

Currently, I am working on implementing resizable sidebars using jQuery and potentially jQueryUI. However, I am encountering an issue with the resizing functionality. Specifically, the right sidebar is causing some trouble in terms of proper resizing, wher ...

How do I adjust the Bootstrap 4 column width to match the size of its content?

I am facing the following situation: [![enter image description here][1]][1] What I want is: Number 1: Adjust the column width to fit the content, in this case the image. Number 2: Resize the column width to accommodate the text "Title of Content" ...

How to create an editable dropdown feature in HTML with Angular 10

Currently, I am using Angular and I am looking for a way to create an editable dropdown in HTML with the help of Angular. Can anyone provide a code snippet for this? ...

Add array as an element within another array

After initializing the data, I have an object structured like this and I am able to push data using the method below: myObj = { 1: ["a", "b", "c"], 2: ["c", "d", "e"], } data: { types: {} }, methods: { pushValue(key, value) { var ...

What is the best way to adjust the size of a background image on Safari

Using Chrome When using Chrome, the functionality is just like what's depicted in the image above. However, when using Safari The issue arises, as it does not work as expected in Safari. See below for the CSS code: background-image: url(r ...

Tips for updating meta tag content in AngularJS single-page apps?

Currently, I am working on developing a single page application with angularjs and need to update the meta tags of the parent page's content. To achieve this, I have implemented the following code: document.getElementsByTagName("META")[5].content = ...

What is the best way to assign the value of a specific key in one array as the key in a different array?

I am attempting to retrieve the value feature_1 associated with the key name from the array data. I then aim to set feature_1 as the key of another array asset, with an array as its corresponding value. For example: //input: data: { name: "feature_1" ...

Reviewing and Implementing React and Material-UI Autocomplete for Selecting Multiple

Having trouble using Formik and MUI Autocomplete with multiple items. Specifically, when searching for "Pencil", it doesn't highlight the item. Also, you can select it twice by clicking on it. Desired outcome: Being able to select one or more items. ...