skip to Main Content

In my table I’ve implemented logic to highlight the Row/Column when the cell is selected but i don’t seem to manage to get the borders on top and bottom of the column correct. The border on the bottom is missing as well as on top and the Header row is excluded as well which it shouldn’t

Screenshot:
The Table with missing Borders

Here is the full code of the iframe

        // Static test data
        const correlationData5y = {
            "Stock A": { "Stock A": 1.0, "Stock B": 0.75, "Stock C": -0.3 },
            "Stock B": { "Stock A": 0.75, "Stock B": 1.0, "Stock C": 0.2 },
            "Stock C": { "Stock A": -0.3, "Stock B": 0.2, "Stock C": 1.0 }
        };

        // Prepare the table
        const tableBody = document.querySelector('#correlationTable tbody');
        const tableHeaders = document.querySelector('#tableHeaders');
        
        // Extract tickers from the keys of the correlation data
        const tickers = Object.keys(correlationData5y);

        // Generate table headers dynamically from the tickers
        const headerRow = document.createElement('th');
        headerRow.textContent = ''; // Top-left corner (empty)
        tableHeaders.appendChild(headerRow);  // Add the empty top-left cell
        tickers.forEach(ticker => {
            const headerCell = document.createElement('th');
            headerCell.textContent = ticker; // Add ticker as header
            tableHeaders.appendChild(headerCell);
        });

        // Helper function to determine the cell color class based on correlation value
        function getCellClass(value) {
            if (value < 0) return 'negative'; // Light blue for negative correlations
            if (value < 0.3) return 'low';     // Medium light blue for low correlations
            if (value < 0.6) return 'medium';  // Medium dark blue for medium correlations
            return 'high';                    // Dark blue for high correlations
        }

        // Create rows for the table dynamically from the data
        tickers.forEach(tickerRow => {
            const row = document.createElement('tr');
            const headerCell = document.createElement('th');
            headerCell.textContent = tickerRow;  // Row header (ticker)
            row.appendChild(headerCell);

            tickers.forEach(tickerCol => {
                const cell = document.createElement('td');
                const value = correlationData5y[tickerRow][tickerCol];
                cell.textContent = value.toFixed(2);  // Show correlation value with 2 decimals
                cell.classList.add('heatmap-cell', getCellClass(value));  // Add the appropriate color class
                row.appendChild(cell);
            });

            tableBody.appendChild(row);
        });

        // Highlight row and column, changing styles only as needed
        const tableCells = document.querySelectorAll('td');
        tableCells.forEach(cell => {
            cell.addEventListener('mouseenter', () => {
                const rowIdx = cell.parentNode.rowIndex;
                const colIdx = cell.cellIndex;

                // Highlight the row
                const row = tableBody.rows[rowIdx - 1]; // Adjust for header row
                row.classList.add('highlight-row');

                // Highlight the column
                tableBody.querySelectorAll('tr').forEach(row => {
                    const targetCell = row.cells[colIdx];
                    if (targetCell) targetCell.classList.add('highlight-column');
                });

                // Highlight the specific cell
                cell.classList.add('highlight-cell');
            });

            cell.addEventListener('mouseleave', () => {
                const rowIdx = cell.parentNode.rowIndex;
                const colIdx = cell.cellIndex;

                // Remove row highlight
                const row = tableBody.rows[rowIdx - 1];
                row.classList.remove('highlight-row');

                // Remove column highlight
                tableBody.querySelectorAll('tr').forEach(row => {
                    const targetCell = row.cells[colIdx];
                    if (targetCell) targetCell.classList.remove('highlight-column');
                });

                // Remove cell highlight
                cell.classList.remove('highlight-cell');
            });
        });
        /* General Page Styling */
        body {
            font-family: 'Arial', sans-serif;
            margin: 20px;
            background-color: #141416;  /* Dark background */
            color: #fff;  /* White text for contrast */
        }

        h2 {
            text-align: center;
            font-size: 20px;  /* Smaller title font */
            margin-bottom: 20px;  /* Reduced space */
            color: #FD6262;  /* Red color for titles */
        }

        table {
            width: 70%;  /* Reduced table width */
            margin: 0 auto;
            border-collapse: collapse;
            box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
            overflow: hidden;
            background-color: #222;  /* Dark table background */
        }

        th, td {
            padding: 8px;  /* Reduced padding */
            text-align: center;
            font-size: 12px;  /* Smaller font size */
            transition: background-color 0.3s ease;
            border: 1px solid #444;  /* Dark border for all sides */
        }

        th {
            background-color: #141416;  
            color: #FD6262;  /* Red color for text */
            font-weight: bold;
        }

        td {
            font-size: 12px;  /* Smaller font size for data */
            color: #fff;  /* White text color for values */
            font-weight: normal;
        }

        /* Gradient color scale for the heatmap (from light blue to dark blue) */
        .negative {
            background-color: rgba(52, 152, 219, 0.2);  /* Light blue for negative correlations */
        }

        .low {
            background-color: rgba(52, 152, 219, 0.4);  /* Medium light blue for low correlations */
        }

        .medium {
            background-color: rgba(52, 152, 219, 0.6);  /* Medium dark blue for medium correlations */
        }

        .high {
            background-color: rgba(52, 152, 219, 1);  /* Dark blue for high correlations */
        }

        /* Hover effect */
        td:hover {
            cursor: pointer;
        }

        /* Container for scroll */
        .table-container {
            overflow-x: auto;
            margin-top: 30px;  /* Adjusted margin */
        }

        /* Highlighted row style */
        .highlight-row {
            border: 2px solid #FD6262;  /* Red border for the row */
            
        }

        /* Highlighted column style */
        .highlight-column {
            border-left: 2px solid #FD6262; /* Red border on the left */
            border-right: 2px solid #FD6262; /* Red border on the right */
          
        }

        /* Highlighted cell style */
        .highlight-cell {
            border: 2px solid #FD6262;  /* Dark red border for the selected cell */
            background-color: rgba(255, 0, 0, 0.2);  /* Light red background for the selected cell */
           /* z-index: 1;  Bring cell to the top if needed */
        }
    <div class="table-container">
        <table id="correlationTable">
            <thead>
                <tr id="tableHeaders">
                    <!-- Table headers will be populated dynamically -->
                </tr>
            </thead>
            <tbody>
                <!-- Table rows will be populated by JavaScript -->
            </tbody>
        </table>
    </div>

Tried to have a consistent Highlighting but there is Boarders missing as you can see in the Image and described above

2

Answers


  1. <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <style>
      /* General Page Styling */
      body {
        font-family: "Arial", sans-serif;
        margin: 20px;
        background-color: #141416; /* Dark background */
        color: #fff; /* White text for contrast */
      }
    
      h2 {
        text-align: center;
        font-size: 20px; /* Smaller title font */
        margin-bottom: 20px; /* Reduced space */
        color: #fd6262; /* Red color for titles */
      }
    
      table {
        width: 70%; /* Reduced table width */
        margin: 0 auto;
        border-collapse: collapse;
        box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
        overflow: hidden;
        background-color: #222; /* Dark table background */
      }
    
      th,
      td {
        padding: 8px; /* Reduced padding */
        text-align: center;
        font-size: 12px; /* Smaller font size */
        transition: background-color 0.3s ease;
        border: 1px solid #444; /* Dark border for all sides */
      }
    
      th {
        background-color: #141416;
        color: #fd6262; /* Red color for text */
        font-weight: bold;
      }
    
      td {
        font-size: 12px; /* Smaller font size for data */
        color: #fff; /* White text color for values */
        font-weight: normal;
      }
    
      /* Gradient color scale for the heatmap (from light blue to dark blue) 
      */
      .negative {
        background-color: rgba(
          52,
          152,
          219,
          0.2
        ); /* Light blue for negative correlations */
      }
    
      .low {
        background-color: rgba(
          52,
          152,
          219,
          0.4
        ); /* Medium light blue for low correlations */
      }
    
      .medium {
        background-color: rgba(
          52,
          152,
          219,
          0.6
        ); /* Medium dark blue for medium correlations */
      }
    
      .high {
        background-color: rgba(
          52,
          152,
          219,
          1
        ); /* Dark blue for high correlations */
      }
    
      /* Hover effect */
      td:hover {
        cursor: pointer;
      }
    
      /* Container for scroll */
      .table-container {
        overflow-x: auto;
        margin-top: 30px; /* Adjusted margin */
      }
    
      /* Highlighted row style */
      .highlight-row {
        border: 2px solid #fd6262; /* Red border for the row */
      }
    
      /* Highlighted column style */
      .highlight-column {
        border-left: 2px solid #fd6262; /* Red border on the left */
        border-right: 2px solid #fd6262;
        border-top: 2px solid #fd6262;
        border-bottom: 2px solid #fd6262; 
    
      /* Highlighted cell style */
      .highlight-cell {
        border: 2px solid #fd6262; /* Dark red border for the selected cell */
        background-color: rgba(
          255,
          0,
          0,
          0.2
        ); /* Light red background for the selected cell */
        /* z-index: 1;  Bring cell to the top if needed */
      }
        </style>
     </head>
      <body>
        <div class="table-container">
          <table id="correlationTable">
          <thead>
           <tr id="tableHeaders">
            <!-- Table headers will be populated dynamically -->
          </tr>
        </thead>
        <tbody>
          <!-- Table rows will be populated by JavaScript -->
        </tbody>
      </table>
     </div>
    
     <script>
      // Static test data
      const correlationData5y = {
        "Stock A": { "Stock A": 1.0, "Stock B": 0.75, "Stock C": -0.3 },
        "Stock B": { "Stock A": 0.75, "Stock B": 1.0, "Stock C": 0.2 },
        "Stock C": { "Stock A": -0.3, "Stock B": 0.2, "Stock C": 1.0 },
      };
    
      // Prepare the table
      const tableBody = document.querySelector("#correlationTable tbody");
      const tableHeaders = document.querySelector("#tableHeaders");
    
      // Extract tickers from the keys of the correlation data
      const tickers = Object.keys(correlationData5y);
    
      // Generate table headers dynamically from the tickers
      const headerRow = document.createElement("th");
      headerRow.textContent = ""; // Top-left corner (empty)
      tableHeaders.appendChild(headerRow); // Add the empty top-left cell
      tickers.forEach((ticker) => {
        const headerCell = document.createElement("th");
        headerCell.textContent = ticker; // Add ticker as header
        tableHeaders.appendChild(headerCell);
      });
    
      // Helper function to determine the cell color class based on 
          correlation value
      function getCellClass(value) {
        if (value < 0) return "negative"; // Light blue for negative 
           correlations
        if (value < 0.3) return "low"; // Medium light blue for low 
          correlations
        if (value < 0.6) return "medium"; // Medium dark blue for medium 
         correlations
        return "high"; // Dark blue for high correlations
        }
    
      // Create rows for the table dynamically from the data
      tickers.forEach((tickerRow) => {
        const row = document.createElement("tr");
        const headerCell = document.createElement("th");
        headerCell.textContent = tickerRow; // Row header (ticker)
        row.appendChild(headerCell);
    
        tickers.forEach((tickerCol) => {
          const cell = document.createElement("td");
          const value = correlationData5y[tickerRow][tickerCol];
          cell.textContent = value.toFixed(2); // Show correlation value with 
       2 decimals
             cell.classList.add("heatmap-cell", getCellClass(value)); // Add 
      the appropriate color class
          row.appendChild(cell);
        });
    
        tableBody.appendChild(row);
      });
    
      // Highlight row and column, changing styles only as needed
      const tableCells = document.querySelectorAll("td");
      tableCells.forEach((cell) => {
        cell.addEventListener("mouseenter", () => {
          const rowIdx = cell.parentNode.rowIndex;
          const colIdx = cell.cellIndex;
    
          // Highlight the row
          const row = tableBody.rows[rowIdx - 1]; // Adjust for header row
          row.classList.add("highlight-row");
    
          // Highlight the column
          tableBody.querySelectorAll("tr").forEach((row) => {
            const targetCell = row.cells[colIdx];
            if (targetCell) targetCell.classList.add("highlight-column");
          });
    
          // Highlight the specific cell
          cell.classList.add("highlight-cell");
        });
    
        cell.addEventListener("mouseleave", () => {
          const rowIdx = cell.parentNode.rowIndex;
          const colIdx = cell.cellIndex;
    
          // Remove row highlight
          const row = tableBody.rows[rowIdx - 1];
          row.classList.remove("highlight-row");
    
          // Remove column highlight
          tableBody.querySelectorAll("tr").forEach((row) => {
            const targetCell = row.cells[colIdx];
            if (targetCell) targetCell.classList.remove("highlight-column");
          });
    
          // Remove cell highlight
          cell.classList.remove("highlight-cell");
          });
        });
     </script>
    </body>
    
    Login or Signup to reply.
  2. It is not normal table structure. Hence, a bit tricky to achieve your desired output.

    If the table was of normal structure then it would have been easier.

    Anyway, I have updated the css code to match your requirement.

    Removed your few css from trs and tds and have added few css to target last rows of the tables and last cells of table columns.

    The hardest part was to achieve to the top border of the table which was added by addition of new css rule (tr#tableHeaders).

    Feel free to ask which part you do not get.

    // Static test data
    const correlationData5y = {
      "Stock A": { "Stock A": 1.0, "Stock B": 0.75, "Stock C": -0.3 },
      "Stock B": { "Stock A": 0.75, "Stock B": 1.0, "Stock C": 0.2 },
      "Stock C": { "Stock A": -0.3, "Stock B": 0.2, "Stock C": 1.0 },
    }
    
    // Prepare the table
    const tableBody = document.querySelector("#correlationTable tbody")
    const tableHeaders = document.querySelector("#tableHeaders")
    
    // Extract tickers from the keys of the correlation data
    const tickers = Object.keys(correlationData5y)
    
    // Generate table headers dynamically from the tickers
    const headerRow = document.createElement("th")
    headerRow.textContent = "" // Top-left corner (empty)
    tableHeaders.appendChild(headerRow) // Add the empty top-left cell
    tickers.forEach((ticker) => {
      const headerCell = document.createElement("th")
      headerCell.textContent = ticker // Add ticker as header
      tableHeaders.appendChild(headerCell)
    })
    
    // Helper function to determine the cell color class based on correlation value
    function getCellClass(value) {
      if (value < 0) return "negative" // Light blue for negative correlations
      if (value < 0.3) return "low" // Medium light blue for low correlations
      if (value < 0.6) return "medium" // Medium dark blue for medium correlations
      return "high" // Dark blue for high correlations
    }
    
    // Create rows for the table dynamically from the data
    tickers.forEach((tickerRow) => {
      const row = document.createElement("tr")
      const headerCell = document.createElement("th")
      headerCell.textContent = tickerRow // Row header (ticker)
      row.appendChild(headerCell)
    
      tickers.forEach((tickerCol) => {
        const cell = document.createElement("td")
        const value = correlationData5y[tickerRow][tickerCol]
        cell.textContent = value.toFixed(2) // Show correlation value with 2 decimals
        cell.classList.add("heatmap-cell", getCellClass(value)) // Add the appropriate color class
        row.appendChild(cell)
      })
    
      tableBody.appendChild(row)
    })
    
    // Highlight row and column, changing styles only as needed
    const tableCells = document.querySelectorAll("td")
    tableCells.forEach((cell) => {
      cell.addEventListener("mouseenter", () => {
        const rowIdx = cell.parentNode.rowIndex
        const colIdx = cell.cellIndex
    
        // Highlight the row
        const row = tableBody.rows[rowIdx - 1] // Adjust for header row
        row.classList.add("highlight-row")
    
        // Highlight the column
        tableBody.querySelectorAll("tr").forEach((row) => {
          const targetCell = row.cells[colIdx]
          if (targetCell) targetCell.classList.add("highlight-column")
        })
    
        // Highlight the specific cell
        cell.classList.add("highlight-cell")
      })
    
      cell.addEventListener("mouseleave", () => {
        const rowIdx = cell.parentNode.rowIndex
        const colIdx = cell.cellIndex
    
        // Remove row highlight
        const row = tableBody.rows[rowIdx - 1]
        row.classList.remove("highlight-row")
    
        // Remove column highlight
        tableBody.querySelectorAll("tr").forEach((row) => {
          const targetCell = row.cells[colIdx]
          if (targetCell) targetCell.classList.remove("highlight-column")
        })
    
        // Remove cell highlight
        cell.classList.remove("highlight-cell")
      })
    })
    /* General Page Styling */
    body {
      font-family: "Arial", sans-serif;
      margin: 20px;
      background-color: #141416; /* Dark background */
      color: #fff; /* White text for contrast */
    }
    
    h2 {
      text-align: center;
      font-size: 20px; /* Smaller title font */
      margin-bottom: 20px; /* Reduced space */
      color: #fd6262; /* Red color for titles */
    }
    
    table {
      width: 70%; /* Reduced table width */
      margin: 0 auto;
      border-collapse: collapse;
      box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
      overflow: hidden;
      background-color: #222; /* Dark table background */
    }
    
    tr {
      border-top: 2px solid #444; /* Dark border for all sides */
      border-left: 2px solid #444;
    }
    
    tr#tableHeaders {
      border-bottom: 0;
    }
    
    th,
    td {
      padding: 8px; /* Reduced padding */
      text-align: center;
      font-size: 12px; /* Smaller font size */
      transition: background-color 0.3s ease;
    }
    th:last-child,
    td:last-child {
      border-right: 2px solid #444;
    }
    td:last-child:hover {
      border-right: 2px solid #fd6262;
    }
    tr:last-child {
      border-bottom: 2px solid #444;
    }
    tr:nth-child(2) {
      border-top: 2px solid #444;
    }
    
    th {
      background-color: #141416;
      color: #fd6262; /* Red color for text */
      font-weight: bold;
    }
    
    td {
      color: #fff; /* White text color for values */
    }
    
    /* Gradient color scale for the heatmap (from light blue to dark blue) */
    .negative {
      background-color: rgba(
        52,
        152,
        219,
        0.2
      ); /* Light blue for negative correlations */
    }
    
    .low {
      background-color: rgba(
        52,
        152,
        219,
        0.4
      ); /* Medium light blue for low correlations */
    }
    
    .medium {
      background-color: rgba(
        52,
        152,
        219,
        0.6
      ); /* Medium dark blue for medium correlations */
    }
    
    .high {
      background-color: rgba(52, 152, 219, 1); /* Dark blue for high correlations */
    }
    
    /* Hover effect */
    th:hover,
    td:hover {
      cursor: pointer;
    }
    
    /* Container for scroll */
    .table-container {
      overflow-x: auto;
      margin-top: 30px; /* Adjusted margin */
    }
    
    /* Highlighted row style */
    
    
    tr.highlight-row {
      border-top: 2px solid #fd6262; /* Red border for the row */
      border-bottom: 2px solid #fd6262; /* Red border for the row */
    }
    
    tr.highlight-row:last-child {
      border-bottom: 2px solid #fd6262; /* Red border for the row */
    }
    
    /* Highlighted column style */
    .highlight-column {
      border-left: 2px solid #fd6262; /* Red border on the left */
      border-right: 2px solid #fd6262; /* Red border on the right */
    }
    
    .highlight-column:last-child {
      border-right: 2px solid #fd6262; /* Red border on the right */
    }
    
    /* Highlighted cell style */
    .highlight-cell {
      border: 2px solid #fd6262; /* Dark red border for the selected cell */
      background-color: rgba(
        255,
        0,
        0,
        0.2
      ); /* Light red background for the selected cell */
      /* z-index: 1;  Bring cell to the top if needed */
    }
    <div class="table-container">
      <table id="correlationTable">
        <thead>
          <tr id="tableHeaders">
            <!-- Table headers will be populated dynamically -->
          </tr>
        </thead>
        <tbody>
          <!-- Table rows will be populated by JavaScript -->
        </tbody>
      </table>
    </div>

    Hope, this helps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search