Achieve borders for the first rows and columns using only CSS

I am currently working on a project involving a system, which you may have already identified as Confluence, and I am looking to enhance the styling of tables within it.

Crucial Note: I am unable to directly adjust the HTML output of the tables; my only option is to apply CSS styles to them. These tables can appear in various combinations on a page and are added by users.

Below is an example illustrating the structure and possible table combinations, although there are other variations as well.

.confluenceTable {
border-collapse: collapse;
}

.confluenceTh, .confluenceTd {
padding: 6px 8px;
border: 1px solid #888a85;
border-right: none;
border-bottom: none;
}

table.confluenceTable tr:first-child .confluenceTh, 
table.confluenceTable tr:first-child .confluenceTd {
border-top: none;
}

.confluenceTh:first-child, .confluenceTd:first-child {
border-left: none;
}



table.confluenceTable thead tr:first-child .confluenceTh {
  border-bottom: 2px solid #CC0018;
}

table.confluenceTable tr .confluenceTh + :not(.confluenceTh) {
  border-left: 2px solid #CC0018; 
}
<h2>First</h2>
<p>table without headers</p>
<table class="confluenceTable">
  <tbody>
    <tr>
      <td class="confluenceTd">1.1</td>
      <td class="confluenceTd">2.1</td>
      <td class="confluenceTd">3.1</td>
    </tr>
    <tr>
      <td class="confluenceTd">1.2</td>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.2</td>
    </tr>
    <tr>
      <td class="confluenceTd">1.3</td>
      <td class="confluenceTd">2.3</td>
      <td class="confluenceTd">3.3</td>
    </tr>
  </tbody>
</table>
<h2>Second</h2>
<p>table with column header</p>
<table class="confluenceTable">
  <thead>
    <tr>
      <th class="confluenceTh">1.1</th>
      <th class="confluenceTh">2.1</th>
      <th class="confluenceTh">3.1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="confluenceTd">1.2</td>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.2</td>
    </tr>
    <tr>
      <td class="confluenceTd">1.3</td>
      <td class="confluenceTd">2.3</td>
      <td class="confluenceTd">3.3</td>
    </tr>
  </tbody>
</table>
<h2>Third</h2>
<p>table with row header</p>
<table class="confluenceTable">
  <tbody>
    <tr>
      <th class="confluenceTh">1.1</th>
      <td class="confluenceTd">2.1</td>
      <td class="confluenceTd">3.1</td>
    </tr>
    <tr>
      <th class="confluenceTh">1.2</th>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.2</td>
    </tr>
    <tr>
      <th class="confluenceTh">1.3</th>
      <td class="confluenceTd">2.3</td>
      <td class="confluenceTd">3.3</td>
    </tr>
  </tbody>
</table>
<h2>Fourth</h2>
<p>table with row and column header</p>
<table class="confluenceTable">
  <thead>
    <tr>
      <!-- This element should also have a border right -->
      <th class="confluenceTh">1.1</th>
      <th class="confluenceTh">2.1</th>
      <th class="confluenceTh">3.1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th class="confluenceTh">1.2</th>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.2</td>
    </tr>
    <tr>
      <th class="confluenceTh">1.3</th>
      <td class="confluenceTd">2.3</td>
      <td class="confluenceTd">3.3</td>
    </tr>
  </tbody>
</table>

The challenge lies with the Fourth table – I have been unsuccessful in adding a border-right to 1.1, which serves as both a column and row header. If anyone has a purely CSS-based solution, your input would be greatly appreciated.

Furthermore, there may be future scenarios where headers are introduced within the middle of a table...

Answer №1

Utilize the nth-of-type pseudo selector as shown below to target the 4th table and apply a right-side border to the first-child th.

The :nth-of-type(an+b) CSS pseudo-class selects an element that has an+b-1 similar siblings before it in the document tree, based on a positive or zero value for n, within a parent element.

table.confluenceTable:nth-of-type(4) > thead > tr > th:first-child{
  border-right: 2px solid #CC0018;
}

.confluenceTable {
border-collapse: collapse;
}

.confluenceTh, .confluenceTd {
padding: 6px 8px;
border: 1px solid #888a85;
border-right: none;
border-bottom: none;
}

table.confluenceTable tr:first-child .confluenceTh, 
table.confluenceTable tr:first-child .confluenceTd {
border-top: none;
}

.confluenceTh:first-child, .confluenceTd:first-child {
border-left: none;
}

table.confluenceTable thead tr:first-child .confluenceTh {
  border-bottom: 2px solid #CC0018;
}

table.confluenceTable tr .confluenceTh + :not(.confluenceTh) {
  border-left: 2px solid #CC0018; 
}
table.confluenceTable:nth-of-type(4) > thead > tr > th:first-child{
  border-right: 2px solid #CC0018; /*Include this*/
}
<h2>First</h2>
<p>table without headers</p>
<table class="confluenceTable">
  <tbody>
    <tr>
      <td class="confluenceTd">1.1</td>
      <td class="confluenceTd">2.1</td>
      <td class="confluenceTd">3.1</td>
    </tr>
    <tr>
      <td class="confluenceTd">1.2</td>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.2</td>
    </tr>
    <tr>
      <td class="confluenceTd">1.3</td>
      <td class="confluenceTd">2.3</td>
      <td class="confluenceTd">3.3</td>
    </tr>
  </tbody>
</table>
<h2>Second</h2>
<p>table with column header</p>
<table class="confluenceTable">
  <thead>
    <tr>
      <th class="confluenceTh">1.1</th>
      <th class="confluenceTh">2.1</th>
      <th class="confluenceTh">3.1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="confluenceTd">1.2</td>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.2</td>
    </tr>
    <tr>
      <td class="confluenceTd">1.3</td>
      <td class="confluenceTd">2.3</td>
      <td class="confluenceTd">3.3</td>
    </tr>
  </tbody>
</table>
<h2>Third</h2>
<p>table with row header</p>
<table class="confluenceTable">
  <tbody>
    <tr>
      <th class="confluenceTh">1.1</th>
      <td class="confluenceTd">2.1</td>
      <td class="confluenceTd">3.1</td>
    </tr>
    <tr>
      <th class="confluenceTh">1.2</th>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.2</td>
    </tr>
    <tr>
      <th class="confluenceTh">1.3</th>
      <td class="confluenceTd">2.3</td>
      <td class="confluenceTd">3.3</td>
    </tr>
  </tbody>
</table>
<h2>Fourth</h2>
<p>table with row and column header</p>
<table class="confluenceTable">
  <thead>
    <tr>
      <!-- This element should also have a right border -->
      <th class="confluenceTh">1.1</th>
      <th class="confluenceTh">2.1</th>
      <th class="confluenceTh">3.1</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th class="confluenceTh">1.2</th>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.2</td>
    </tr>
    <tr>
      <th class="confluenceTh">1.3</th>
      <td class="confluenceTd">2.3</td>
      <td class="confluenceTd">3.3</td>
    </tr>
  </tbody>
</table>

Answer №2

Your query, in a broader context
The HTML structure outlined is as follows.

element.A1
  element.A2
element.B1
  element.B2

Now, the objective is to style A2 based on certain characteristics of B2. For instance, if B2 is present, if it belongs to a specific type of element (such as a div or span), if it possesses a particular attribute ([data-foo="bar"]), and so forth.

Resolving with CSS
Regrettably, achieving this solely using CSS is currently unattainable. This limitation exists because all CSS selectors target elements descending from a specified element, but not vice versa. For example, a b selects every b element that is a descendant of a. With a > b, only child elements of a are considered. There is no direct way to reverse this behavior.

Resolving with JS + CSS
For now, the issue can be addressed by employing a designated class and applying it through JavaScript. The approach would resemble something like the following.

.A1.special .A2 {
    /* distinctive styling for A2 */
}
var b2s = document.querySelectorAll('.B2'), i;
for (i = 0; i < b2s.length; ++i) {
    if (isSpecial(b2s[i])) {
        b2s[i].parentNode.previousSibling.classList.add('special');
    }
}

References: querySelectorAll, parentNode, previousSibling, classList.

The function isSpecial would verify any desired properties. Specifically, your question has been executed in the below script.

// identify special case and add CSS class for styling
var firstRows = document.querySelectorAll('.confluenceTable tbody > tr:first-child'), i;
for (i = 0; i < firstRows.length; ++i) {
  if (firstRows[i].querySelector('th') !== null) {
    firstRows[i].parentNode.parentNode.classList.add('special');
  }
}
.confluenceTable {
border-collapse: collapse;
}

.confluenceTh, .confluenceTd {
padding: 6px 8px;
border: 1px solid #888a85;
border-right: none;
border-bottom: none;
}

table.confluenceTable tr:first-child .confluenceTh, 
table.confluenceTable tr:first-child .confluenceTd {
border-top: none;
}

.confluenceTh:first-child, .confluenceTd:first-child {
border-left: none;
}

table.confluenceTable thead tr:first-child .confluenceTh {
  border-bottom: 2px solid #CC0018;
}

table.confluenceTable tr .confluenceTh + :not(.confluenceTh) {
  border-left: 2px solid #CC0018; 
}

/* apply styles for the exceptional scenario */
table.confluenceTable.special > thead > tr > th:first-child{
  border-right:2px solid #CC0018;
}
<h2>First</h2>
<p>table without headers</p>
<table class="confluenceTable">
  <tbody>
    <tr>
      <td class="confluenceTd">1.1</td>
      <td class="confluenceTd">2.1</td>
      <td class="confluenceTd">3.1</td>
    </tr>
    <tr>
      <td class="confluenceTd">1.2</td>
      <td class="confluenceTd">2.2</td>
      <td class="confluenceTd">3.

......(remaining content omitted for brevity)....... 

..</td>
    </tr>
  </tbody>
</table>

Answer №3

Give this a shot:

body > .confluenceTable:nth-child(12) thead tr:first-child th:first-child   {
    border-right: 2px solid #CC0018; 
}

Check out this live demonstration - https://jsfiddle.net/grinmax_/wxfL4ocg/

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

What is the best way to determine the click position on a square-shaped element?

Is there a way to retrieve the precise position of a square element when it is clicked on? ...

Trouble concealing information in Gmail and Outlook, issue persists

I need to create an email with two different links, one to be visible only in Gmail and the other only in Outlook. I discovered that I should use mso-hide for Outlook and display none for Gmail, but neither seem to be working as expected. When I use displa ...

Arrangement of p tag and br tag in HTML

This is what I desire. https://i.sstatic.net/jhwrp.png This is what I am receiving. https://i.sstatic.net/quwUN.png This is the code I have written. I am struggling with the spacing. Aligning the p tag with the br tag is proving to be a challenge for me. ...

What CSS property can be used to make short words wrap to the next line?

Is it possible to automatically identify if a line of text ends with a short word and then move it to the next line, so that the text flows smoothly? This would ensure a more organized layout. For instance, I envision the following text: Cascading Style ...

Guidelines for choosing a dropdown menu option using jQuery in a WordPress photo gallery

First off, take a look at the screenshot to understand what I'm trying to accomplish: Within WordPress, after clicking on "New Post" and then on the "Add Media" button, a pop-up image gallery appears with an image filtering drop-down menu. My goal is ...

Tips and tricks for utilizing a document to paraphrase a paragraph

document.getElementById("txtOutput").value = result; Is there a way to rewrite the code so that instead of using .value=result, it writes to a specific div or paragraph? ...

I'm wondering why my element is aligning itself with its sibling. It seems that when the parent has overflow set to hidden, it causes the children's

Let me break down the diagram below for you: The main box is marked in yellow and serves as the parent element. Within this parent box, there are two child elements, one in black and one in cyan. To hide any excess content of the cyan box that overfl ...

Adjustable width box with shortened text

My challenge is to arrange 4 divs side by side, with the first two on the left, the fourth on the right, and the third filling the remaining space in between. The third div should have a dynamic width and contain two text lines that should support ellipsis ...

Is there a way for my element to fill the entire screen and prevent any scrolling from occurring?

I am looking to ensure that my children's div occupies the remaining space on the screen and prevent scrolling. Since I am utilizing PanZoom, I need the children's div to always fill 100% of the screen. <div class="parent"> &l ...

Use JavaScript to add closing tags before opening tags in your code

Within my HTML file, I have the following structure: <ol> <li></li> <li></li> <li><span id="cursor"></span></li> <li></li> </ol> I am looking to divide the list into two at ...

Accessing data from a CD-ROM or DVD through a web browser

I am currently working on developing a web application for a friend that will enable users to simply click a button to upload all the content from the CD-ROM or DVD they have inserted directly to a server. It's not feasible to rely on the standard br ...

PHP and AJAX successfully retrieving data, but failing to redirect to new page

I am trying to pass a username and password to a PHP page using AJAX, and once the credentials are verified, I want to load the main.html page. Currently, when I submit the form, I receive a response of "true," which displays above the form where an error ...

How can I position an image in between buttons using CSS?

I need help with my website layout, specifically with the arrangement of elements: <div><Label> <Button1><Image><Button2></div> Unfortunately, the div is not displaying in a single line as ...

What is the best way to place focus following text?

<script> function setupTextarea(){ var textBox = document.getElementById('q'); textBox.focus(); textBox.value = textBox.value; } </script> <body onload="setupTextarea();"> <textarea name='q' rows='3' col ...

Removing child elements from a div without actually removing them from the document

I am trying to achieve a specific goal with Jquery or vanilla JS: clearing the inner text only of a div along with its child elements, while keeping all elements intact after the operation. In my scenario, the target div is denoted as student_profile. Aft ...

Can you direct me to resources on the internet that provide information about support for 12 Bit color depth?

I am curious to know when the w3specs will support colors in 12 bits instead of the current 8-bit format used for webcolors like sRGB (#FFFFFF or rgba(255,0,0,100). I wonder if there will ever be a new standard called 12-Bit sRGB where colors can be defin ...

The presence of absolute positioned elements is causing the appearance of a horizontal scrollbar

On my webshop's categoria page, I have implemented sliders to filter products based on price ranges. The issue arises when viewing the site on mobile devices, as a horizontal scrollbar appears due to the absolute positioning of these sliders and thei ...

insert a tag in a div using the Greasemonkey extension

I stumbled across a website with a div that looks like this: <div class="xyz"> <a href="https://www.google.co.in/search?q=joker" target="abc">google</a> <a href="https://www.youtube.com/search?q=joker" target="abc">youtube& ...

What is the best way to conduct a comparison between text within an HTML element and a particular value contained in an array of objects

My first attempt at creating a quiz app using JavaScript has hit a roadblock. I am facing an issue with calculating the user's score based on their selected answers and the correct ones. The userScore variable is not incrementing as expected, always s ...

When utilizing React, I generated an HTML page with a distinct .js file, however, encountered two unexpected errors

Update : Gratitude to everyone who has helped me in tackling this issue. One user suggested using a web server, but my intention was to find a solution using just a single HTML and JS file. Even though I tried following the steps from a similar question o ...