skip to Main Content

I need to make a table like in the screenshot: what it should look like

What result did I get: my result

Problem: I can’t make a green border like in the screenshot for the "registered" column.

Q: How can I make this border if it’s a table?

I tried to rewrite it on div but nothing worked

My styles

.container {
  table {
    width: 100%;
    border-collapse: collapse;

    thead {
      tr {
        th {
          padding-bottom: 18px;
          width: 230px;
          &:first-child{
            text-align: left;
          }
        }
      }

      border-bottom: 1px solid rgba(101, 97, 123, 0.3);
    }

    tbody {
      tr {

        .doubled-content {
          text-align: center;

          span {
            font-style: italic;
            font-weight: 400;
            font-size: 12px;
            line-height: 14px;
            letter-spacing: 0.15px;
            color: #65617B;
          }

          .content-title {
            font-style: normal;
            font-weight: 700;
            font-size: 18px;
            line-height: 24px;
            letter-spacing: 0.15px;
            color: #65617B;
          }
        }

        .plan-content{
          text-align: center;
          font-style: normal;
          font-weight: 700;
          font-size: 18px;
          line-height: 24px;
          letter-spacing: 0.15px;
          color: #65617B;
        }

        .guarantee{
          display: flex;
          align-items: center;
          gap: 24px;

          .text-wrapper{
            display: flex;
            flex-direction: column;

            div{
              font-style: normal;
              font-weight: 400;
              font-size: 18px;
              line-height: 20px;
              display: flex;
              align-items: center;

              color: #65617B;
            }

            span{
              font-family: 'Helvetica';
              font-style: normal;
              font-weight: 400;
              font-size: 14px;
              line-height: 16px;
              letter-spacing: 0.15px;
              width: 350px;

              color: #65617B;
            }
          }

          &__btn{
            display: flex;
            justify-content: center;
            align-items: center;
          }
        }

        td{
          padding-bottom: 18px;
          vertical-align: middle;

          &:first-child{
            padding-top: 18px;
            width: 500px;
          }
        }
      }

      .expanded-row-item{
        td{
          padding: 10px;
          vertical-align: middle;
          text-align: center;

          &:first-child{
            text-align: left;
          }
        }
        .row-title{
          font-style: normal;
          font-weight: 400;
          font-size: 14px;
          line-height: 18px;
          letter-spacing: 0.15px;
          color: #65617B;
        }
      }
    }

    // other

    .plan-title {
      font-family: 'Helvetica', serif;
      font-style: normal;
      font-weight: 700;
      font-size: 22px;
      line-height: 24px;
      letter-spacing: 0.15px;

      color: #000000;
    }
    .plan-title-content {
      font-family: 'Helvetica', serif;
      font-style: normal;
      font-weight: 700;
      font-size: 22px;
      line-height: 24px;
      letter-spacing: 0.15px;
      text-align: center;

      color: #000000;
    }
  }
}

My code

import React from "react";
import Image from "next/image";
import CustomButton from "../kit/buttons/CustomButton";
import styles from "../../styles/components/plan.module.scss";
import { Icons } from "../../lib/constants/icons";

const Plan = () => {

  const [firstRowExpanded, setFirstRowExpanded] = React.useState(false);
  const [secondRowExpanded, setSecondRowExpanded] = React.useState(false);
  const [thirdRowExpanded, setThirdRowExpanded] = React.useState(false);


  return (
    <div className={styles["container"]}>
      <table>
        <thead>
        <tr>
          <th className={styles["plan-title"]}>Detailed plan overview</th>
          <th className={styles["plan-title-content"]}>Unregistered</th>
          <th className={styles["plan-title-content"]}>Registered</th>
          <th className={styles["plan-title-content"]}>Professional</th>
        </tr>
        </thead>
        <tbody>
        <tr>
          <td className={styles["plan-title"]} onClick={() => setFirstRowExpanded(!firstRowExpanded)}>
            Investment tools &nbsp;
            {Icons.chevron_right}
          </td>
          <td className={styles["doubled-content"]}>
            <span>Full free version</span>
            <div className={styles["content-title"]}>Limited</div>
          </td>
          <td className={styles["doubled-content"]}>
            <span>No credit card need</span>
            <div className={styles["content-title"]}>Advanced</div>
          </td>
          <td className={styles["doubled-content"]}>
            <span>29$ / month</span>
            <div className={styles["content-title"]}>Full version</div>
          </td>
        </tr>

        <tr>
          <td className={styles["plan-title"]} onClick={() => setSecondRowExpanded(!secondRowExpanded)}>Community &nbsp;
            {Icons.chevron_right}
          </td>
          <td className={styles["plan-content"]}>
            Limited
          </td>
          <td className={styles["plan-content"]}>
            Advanced
          </td>
          <td className={styles["plan-content"]}>
            Full version
          </td>
        </tr>

        <tr>
          <td className={styles["plan-title"]} onClick={() => setThirdRowExpanded(!thirdRowExpanded)}>Other support &nbsp;
            {Icons.chevron_right}
          </td>
          <td className={styles["plan-content"]}>
            Limited
          </td>
          <td className={styles["plan-content"]}>
            Advanced
          </td>
          <td className={styles["plan-content"]}>
            Full version
          </td>
        </tr>

        <tr>
          <td className={styles["guarantee"]}>
            <Image src={"/images/shared/garantee.svg"} width={61} height={61} />
            <div className={styles["text-wrapper"]}>
              <div>30-Day 100% money back guarantee</div>
              <span>
                You are not charged until the trial ends.
                Subscription fee may be tax deductible.
              </span>
            </div>
          </td>
          <td>
            <div className={styles['guarantee__btn']}>
              <CustomButton text={"Your version"} width={195} height={50} />
            </div>
          </td>
          <td>
            <div className={styles['guarantee__btn']}>
              <CustomButton text={"Free sign up"} width={195} height={50} />
            </div>
          </td>
          <td>
            <div className={styles['guarantee__btn']}>
              <CustomButton text={"GET PRO"} width={195} height={50} />
            </div>
          </td>
        </tr>
        </tbody>
      </table>
    </div>
  );
};

export default Plan;

2

Answers


  1. Using a table could be the wrong approach here, it makes things like this a bit complicated. You do have tabular data, but you also need to show stuff (like this border) that isn’t really tabular. It could be done with a table, but things like those rounded corners will be hard.

    I have two suggestions. One is to just keep your code as-is but have a large div that’s just transparent with a border on it that you can move around on top of that table You can make it so you can click through it, but you will most likely have to use position:absolute to place it where you want it.

    .column-highlight {
      border: 2px solid limegreen;
      border-radius: 10px;
      position: absolute;
      top: 7px;
      left: 375px;
      width: 110px;
      height: 174px;
      pointer-events: none;
    }
    <div>
    
      <div class="column-highlight"></div>
    
      <table>
        <thead>
        <tr>
          <th>Detailed plan overview</th>
          <th>Unregistered</th>
          <th>Registered</th>
          <th>Professional</th>
        </tr>
        </thead>
        <tbody>
        <tr>
          <td>Investment tools</td>
          <td>
            <span>Full free version</span>
            <div>Limited</div>
          </td>
          <td>
            <span>No credit card need</span>
            <div>Advanced</div>
          </td>
          <td>
            <span>29$ / month</span>
            <div>Full version</div>
          </td>
        </tr>
    
        <tr>
          <td>Community</td>
          <td>Limited</td>
          <td>Advanced</td>
          <td>Full version</td>
        </tr>
    
        <tr>
          <td>Other support</td>
          <td>Limited</td>
          <td>Advanced</td>
          <td>Full version</td>
        </tr>
    
        <tr>
          <td style="width: 250px;">
            <div>
              <div>30-Day 100% money back guarantee</div>
              <span>
                You are not charged until the trial ends.
                Subscription fee may be tax deductible.
              </span>
            </div>
          </td>
          <td>
            <button type="button">Your version</button>
          </td>
          <td>
            <button type="button">Free sign up</button>
          </td>
          <td>
            <button type="button">Get Pro</button>
          </td>
        </tr>
        </tbody>
      </table>
    </div>

    It’s not a perfect example but you get the idea I think.


    The other way (which I think is better option) would be to remove the table and use divs in a flexbox aligned horizontally. Then your data is grouped together, plus it’s very easy to just add a class to a column/div to give it a highlight border.

    #plan-container{
      display: flex;
    }
    
    .plan {
      padding: 5px;
    }
    
    #plan-overview {
      width: 250px;
    }
    
    .plan-selected {
      border: 2px solid limegreen;
      border-radius: 10px;
    }
    <div id="plan-container">
      <div class="plan" id="plan-overview">
        <strong class="plan-title">Detailed Plan Overview</strong>
        <p>Investment tools</p>
        <p>Community</p>
        <p>30-Day 100% money back guarantee. <span>
          You are not charged until the trial ends.
          Subscription fee may be tax deductible.
        </span></p>
      </div>
      <div class="plan">
        <strong class="plan-title">Unregistered</strong>
        <p>Full free version</p>
        <p>Limited</p>
        <p>Limited</p>
        <p>Limited</p>
        <button type="button">Your version</button>
      </div>
      <div class="plan plan-selected">
        <strong class="plan-title">Registered</strong>
        <p>No credit card need</p>
        <p>Advanced</p>
        <p>Advanced</p>
        <p>Advanced</p>
        <button type="button">Free sign up</button>
      </div>
      <div class="plan">
        <strong class="plan-title">Professional</strong>
        <p>29$ / month</p>
        <p>Full Version</p>
        <p>Full Version</p>
        <p>Full Version</p>
        <button type="button">Get Pro</button>
      </div>
    </div>

    Again, my example is imperfect and some data might wrap to take up more lines than it should, but that can be fixed and it’s not displayed as best as it could be inside the snippet thing here on SO.

    Login or Signup to reply.
  2. While I can see @finitelooper’s contention that for styling purposes it is easier to do away with the table structure, I’m uncomfortable with the removal of the semantics this implies.

    The data is, after all, tabular.

    This snippet offers a different approach – putting the green border on before pseudo elements on the relevant td and th cells.

    The curves are achieved by putting top/bottom border as relevant on the first th and last td.

    The code could do with a bit of refinement when it comes to how much the increase in size (the 10px) should actually be, but this is just a demo:

    <style>
      td span {
        font-size: 8px;
      }
      
      tr td:nth-child(3),
      tr th:nth-child(3) {
        position: relative;
      }
      
      tr td:nth-child(3)::before,
      tr th:nth-child(3)::before {
        rbackground: pink;
        content: '';
        position: absolute;
        left: 0;
        top: -5px;
        bottom: -5px;
        display: inline-block;
        width: 100%;
        z-index: -1;
        border: solid 1px lime;
        border-width: 0px 1px 0px 1px;
      }
      
      tr:first-child th:nth-child(3)::before {
        border-width: 1px 1px 0 1px;
        border-radius: 10px 10px 0 0;
      }
      
      tr:last-child td:nth-child(3)::before {
        border-width: 0px 1px 1px 1px;
        border-radius: 0 0 10px 10px;
      }
    </style>
    <div>
    
      <div class="column-highlight"></div>
    
      <table>
        <thead>
          <tr>
            <th>Detailed plan overview</th>
            <th>Unregistered</th>
            <th>Registered</th>
            <th>Professional</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Investment tools</td>
            <td>
              <span>Full free version</span>
              <div>Limited</div>
            </td>
            <td>
              <span>No credit card need</span>
              <div>Advanced</div>
            </td>
            <td>
              <span>29$ / month</span>
              <div>Full version</div>
            </td>
          </tr>
    
          <tr>
            <td>Community</td>
            <td>Limited</td>
            <td>Advanced</td>
            <td>Full version</td>
          </tr>
    
          <tr>
            <td>Other support</td>
            <td>Limited</td>
            <td>Advanced</td>
            <td>Full version</td>
          </tr>
    
          <tr>
            <td style="width: 250px;">
              <div>
                <div>30-Day 100% money back guarantee</div>
                <span>
                You are not charged until the trial ends.
                Subscription fee may be tax deductible.
              </span>
              </div>
            </td>
            <td>
              <button type="button">Your version</button>
            </td>
            <td>
              <button type="button">Free sign up</button>
            </td>
            <td>
              <button type="button">Get Pro</button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search