skip to Main Content

I am trying to create a faq section for my webpage.

At first I used custom tags (Not registered just used custom names) and it worked fine but later I thought this could impact SEO so I moved from custom tag to vanilla div.

The custom tag version was working fine but as soon as I moved to div the CSS started behaving weirdly.

This is the code I am using and the FAQ.css and the script that adds and removes the CSS :

* {
    padding: 0;
    margin: 0;
}

body {
    gap: 10px;
    display: grid;
    padding: 20px;
    justify-content: center;
    background-color: rgb(185, 206, 185);

}

#faq {
    display: grid;
    text-align: center;
    padding: 20px 30px;
    justify-content: center;
    background-color: white;
}

faqItem {
    display: grid;
    overflow: hidden;
    text-align: left;
    background-color: rgb(194, 204, 204);
}

faqItem::after {
    display: grid;
    content: "";
    padding-top: 10px;
    border-bottom: 2px solid rgb(63, 60, 63);
}

faqItem h1 {
    display: grid;
    min-width: 95%;
    font-size: 24px;
    padding: 5px 10px 0 10px;
    cursor: pointer;
}

faqItem h1::before {
    display: grid;
    content: "+";
    width: fit-content;
    margin-bottom: -30px;
    justify-self: right;
    transition: transform 0.2s ease;
}

faqItem p {
    visibility: hidden;
    max-width: 70ch;
    max-height: 0;
    font-size: 14px;
    line-height: 18px;
    padding: 5px 10px;
    color: #3b3b3b;
    transition: max-height 0.2s ease-in-out, visibility 0.15s ease;
}

/* Classes for Div */

.faqItem {
    display: grid;
    overflow: hidden;
    text-align: left;
    background-color: rgb(194, 204, 204);
}

.faqItem::after {
    display: grid;
    content: "";
    padding-top: 10px;
    border-bottom: 2px solid rgb(63, 60, 63);
}

.faqItem h1 {
    display: grid;
    min-width: 95%;
    font-size: 24px;
    padding: 5px 10px 0 10px;
    cursor: pointer;
}

.faqItem h1::before {
    display: grid;
    content: "+";
    width: fit-content;
    margin-bottom: -30px;
    justify-self: right;
    transition: transform 0.2s ease;
}

.faqItem p {
    visibility: hidden;
    max-width: 70ch;
    max-height: 0;
    font-size: 14px;
    line-height: 18px;
    padding: 5px 10px;
    color: #3b3b3b;
    transition: max-height 0.2s ease-in-out, visibility 0.15s ease;
}

/* Common Class */
.changeIcon::before {
    content: "-";
    transform: rotate(180deg);
    transition: content;
}

.showContent {
    overflow: hidden;
    max-height: 300px;
    visibility: visible;
    transition: max-height 0.5s ease-in;
} 
<link rel="stylesheet" href="faq.css">

<body>

<!-- Custom Tag -->

<article id="faq">
  <header>
      <h1>FAQs</h1>
  </header>

  <faqItem>
      <h1>Some My title</h1>
      <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Nam nulla atque, mollitia ducimus sit ut
          pariatur non ex vel asperiores voluptatibus eos est optio sequi nihil porro voluptates, repudiandae
          quam!
      </p> 
  </faqItem>
</article>

<!-- Vanilla Div -->

<article id="faq">
  <header>
      <h1>FAQs</h1>
  </header>

  <div class="faqItem">
      <h1>Some My title</h1>
      <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Nam nulla atque, mollitia ducimus sit ut
          pariatur non ex vel asperiores voluptatibus eos est optio sequi nihil porro voluptates, repudiandae
          quam!
      </p>
  </div>
</article>
</body> 

<script>
  // Function that will expand and shrink the faqItem
  function updateFAQItemState(elem) {
      elem.classList.contains("changeIcon")
          ? elem.classList.remove("changeIcon")
          : elem.classList.add("changeIcon");

      elem.nextElementSibling.classList.contains("showContent")
          ? elem.nextElementSibling.classList.remove("showContent")
          : elem.nextElementSibling.classList.add("showContent");
  }

  // Using Custom Tags (Not registered)
  let customFaqItems = [...document.getElementsByTagName("faqItem")];

  customFaqItems.forEach(element => {
      let h1 = element.getElementsByTagName("h1")[0];
      h1.onclick = function (ele) {
          updateFAQItemState(ele.target);
      }
  });
  // using DIV

  let divfaqItem = [...document.getElementsByClassName("faqItem")];
  divfaqItem.forEach(element => {
      let h1 = element.getElementsByTagName("h1")[0];
      h1.onclick = function (ele) {
          updateFAQItemState(ele.target);
      }
  })
</script> 

JSFiddle link: https://jsfiddle.net/fk6xbezw/1/

Question One :

Why the CSS is not working as expected?

Question Second :

Does using custom tag hurts SEO? (Registered or Unregistered if applicable)

2

Answers


  1. Your CSS definitions in

    .faqItem p {
    }
    

    have precedence over those in

    .showContent {
    }
    

    which negates almost all of the effects inside the .showContent { .. } block. You could change .showContent { to .faqItem p.showContent { for example to circumvent that.


    Why ?

    In your old situation, while using a <faqItem> element, these 2 blocks of CSS contained the relevant code:

    faqItem p {
        ...
        visibility: hidden;
        ...
    }
    
    .showContent {
        ...
        visibility: visible;
        ...
    }
    

    When you switched from using <faqItem> to <div class="faqItem"> you changed

    faqItem p {
        ...
    }
    

    to:

    .faqItem p {
        ...
    }
    

    which is totally the right thing to do, and in most cases works out just fine, however the devil lies in the details as they say.

    The statement faqItem p is a combination of two element-selectors; as in "for any p element located under a faqItem element …".
    The statement .faqItem p however, is one class-selector and one element-selector, and using a class-selector gives that block of CSS a higher level of specificity.

    often enough, that won’t matter much; but in your case you are trying to overrule the visibility-property (and others) inside here, with a visibility-property in .showContent.

    Since .showContent consists of a single class-selector (which is pretty specific), it used to beat out those weak faqItem pelement-selectors.
    However, since your new .faqItem p uses a class-selector plus an element-selector, it is more specific than .showContent which is only a class-selector by itself.


    So, the fix ?

    /* Changing: */
    .showContent { ... }
    /* To: */
    .faqItem .showContent { ... }
    /* Or: */
    .faqItem p.showContent { ... }
    

    Changes the specificity of the .showContent so it again outweighs the .faqItem p.

    You can read up more about specificity (and other rules of precedence) on many places, such as here.

    There are alternate ways of accomplishing the same result. Some have been recommended in other comments now, but i feel fairly confident to claim those methods are less appropriate. It’s worth knowing the rules of precedence and structuring your CSS to that affect.

    Those other methods are similar to not understanding the rules of precedence for mathematical operators, and recommending people should write (5*5) + (6*6) at all times.


    Login or Signup to reply.
  2. You can simplify the Javascript a little by using a delegated event listener bound to the .faqItem div elements but trigger the necessary accordion type code only when the event is actually registered upon the H1 element.

    By negating the css content within .faqItem p ( ie: .faqItem p:not(.showContent) ) it seems to behave as expected?!

    document.querySelectorAll('.faqItem').forEach(div=>{
        div.addEventListener('click',(e)=>{
            if( e.target.tagName=='H1' ){
                let el=e.target;
                el.classList.toggle( 'changeIcon' );
                el.nextElementSibling.classList.toggle( 'showContent' )
            }
        })
    })
    * {
        padding: 0;
        margin: 0;
    }
    body {
        gap: 10px;
        display: grid;
        padding: 20px;
        justify-content: center;
        background-color: rgb(185, 206, 185);
        
    }
    
    .faq {  /* ID attributes must be unique in the DOM !! */
        display: grid;
        text-align: center;
        padding: 20px 30px;
        justify-content: center;
        background-color: white;
    }
    
    
    /* Classes for Div */
    
    .faqItem {
        display: grid;
        overflow: hidden;
        text-align: left;
        background-color: rgb(194, 204, 204);
    }
    
    .faqItem::after {
        display: grid;
        content: "";
        padding-top: 10px;
        border-bottom: 2px solid rgb(63, 60, 63);
    }
    
    .faqItem h1 {
        display: grid;
        min-width: 95%;
        font-size: 24px;
        padding: 5px 10px 0 10px;
        cursor: pointer;
    }
    
    .faqItem h1::before {
        display: grid;
        content: "+";
        width: fit-content;
        margin-bottom: -30px;
        justify-self: right;
        transition: transform 0.2s ease;
    }
    
    .faqItem p:not(.showContent) {
        visibility: hidden;
        max-width: 70ch;
        max-height: 0;
        font-size: 14px;
        line-height: 18px;
        padding: 5px 10px;
        color: #3b3b3b;
        transition: max-height 0.2s ease-in-out, visibility 0.15s ease;
    }
    
    /* Common Class */
    .changeIcon::before {
        content: "-";
        transform: rotate(180deg);
        transition: content;
    }
    
    .showContent {
        overflow: hidden;
        max-height: 300px;
        visibility: visible;
        transition: max-height 0.5s ease-in;
    }
    <article class="faq">
        <header>
            <h1>FAQs</h1>
        </header>
    
        <div class="faqItem">
            <h1>Some My title #1</h1>
            <p>Lorem ipsum dolor sit, amet consectetur adipisicing elit. Nam nulla atque, mollitia ducimus sit ut
                pariatur non ex vel asperiores voluptatibus eos est optio sequi nihil porro voluptates, repudiandae
                quam!
            </p>
        </div>
    </article>
    
    
    <article class="faq">
        <header>
            <h1>FAQs</h1>
        </header>
    
        <div class="faqItem">
            <h1>Some My title #2</h1>
            <p>
            vel asperiores voluptatibus eos est optio sequi consectetur adipisicing elit. Nam nulla atque, mollitia ducimus sit ut
                pariatur non ex.
            </p>
        </div>
    </article>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search