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
Your CSS definitions in
have precedence over those in
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:When you switched from using
<faqItem>
to<div class="faqItem">
you changedto:
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 twoelement-selector
s; as in "for anyp
element located under afaqItem
element …".The statement
.faqItem p
however, is oneclass-selector
and oneelement-selector
, and using aclass-selector
gives that block of CSS a higher level ofspecificity
.often enough, that won’t matter much; but in your case you are trying to overrule the
visibility
-property (and others) inside here, with avisibility
-property in.showContent
.Since
.showContent
consists of a singleclass-selector
(which is pretty specific), it used to beat out those weakfaqItem p
–element-selector
s.However, since your new
.faqItem p
uses aclass-selector
plus anelement-selector
, it is more specific than.showContent
which is only aclass-selector
by itself.So, the fix ?
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.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?!