I have a blockquote like this:

<blockquote class="spoiler">Soopah sekkrit!</blockquote>

I want to make it hidden, only showing it if the user hovers over it. I'm doing it now with JS:

blockquote.addEventListener('mouseover', function() {
    this.style.height = this.offsetHeight + 'px';
    this.dataset.contents = this.innerHTML;
    this.innerHTML = '';
});
blockquote.addEventListener('mouseout', function() {
    this.style.height = '';
    this.innerHTML = this.dataset.contents;
});

Is there a better way to do this, with CSS?

It has to keep its background-color, size, and work for contents with custom colors. If possible, I'd also like to animate it so the contents fade in gradually.

Here's a strategy that works pretty well, looks nice, and has pretty clean transitions

.spoiler {
    position: relative;
    display: inline-block;
    cursor: help;
}
.spoiler::before {
    content: 'psst\02026'; /* &hellip; */
    position: absolute;
    left: -2px;
    top: -2px;
    right: -2px;
    bottom: -2px;
    border-radius: 1px;
    font-size: .9rem;
    color: #e6578c;
    background: #ffe5e5;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    opacity: 1;
    transition: opacity 0.7s ease, transform 0.3s ease; /* hide faster than reveal */
}
.spoiler:hover::before {
    opacity: 0;
    transform: translateY(-50%)rotateX(80deg);
    transition: opacity 1.0s ease, transform 0.5s ease; /* slower reveal */
}

If you style the parent block with opacity: 0 without hover, then you can't add any styles to illustrate what part of the page the user should be hovering over.

Instead, if we add a ::before element that covers up the child content, then we can fade it out on hover and still provide a visual indication of where to go.

Demo in Stack Snippets

Spoiler Demo

<!-- begin snippet: js hide: true console: true babel: false --> <!-- language: lang-css -->
.spoiler {
    position: relative;
    display: inline-block;
    cursor: help;
}
.spoiler::before {
    content: 'psst\02026'; /* &hellip; */
    position: absolute;
    left: -2px;
    top: -2px;
    right: -2px;
    bottom: -2px;
    border-radius: 1px;
    font-size: .9rem;
    color: #e6578c;
    background: #ffe5e5;
    text-align: center;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 1;
    transition: opacity 0.7s ease, transform 0.3s ease; /* hide faster than reveal */
}
.spoiler:hover::before {
    opacity: 0;
    transform: translateY(-50%)rotateX(80deg);
    transition: opacity 1.0s ease, transform 0.5s ease; /* slower reveal */
}




/* demo styles */
blockquote {
  margin: 0
}
<!-- language: lang-html -->
<p>
  Inline Spoiler <span class="spoiler" > Word </span>
</p>

<p class="spoiler">
  Paragraph Text Block of a Spoiler
</p>

<blockquote class="spoiler">
  Block quote spoiler with super long text that wraps and wraps and wraps some more.
  
  Block quote spoiler with super long text that wraps and wraps and wraps some more.
  
  Block quote spoiler with super long text that wraps and wraps and wraps some more.
</blockquote>
<!-- end snippet -->