Sometimes the best way to learn is by knowing what not to do.
I recently began managing a WordPress site, and by managing I mean fixing the huge mess of technical debt while trying to add a few new things while waiting on my laptop to be repaired so I can make a brand new site. One of those new things are a series of recently recorded promo videos. Per my advice, they are being uploaded to the site for embedding rather than being posted to YouTube and dealing with the mass amount of JS it loads.
What I wanted to do was put the videos at the top of page and center them. In this way, they are prominent and visible. However, WordPress will not allow that. It lacks the ability to center or right align videos, only default left-align. OK, this shouldn't be too hard to fix. Just write a bit of CSS and add a class to the markup. Tada!
Except with WordPress, nothing is ever that simple.
See, when embedding videos, WordPress uses it's own shortcode format which is internally translated into the appropriate markup. The shortcode also lacks a way to add a class to the resulting markup.
<!-- It is so close to raw HTML yet so, so far -->
[video width="1280" height="720" mp4="http://www.example.com/wp-content/uploads/2016/03/promo-video.mp4"][/video]
Now I could still fix this in CSS. Rendered, this shortcode turns into a <div class="wp-video"></div> containing all subsequent markup. All I have to do is center the div:
.wp-video {
margin-right: auto;
margin-left: auto;
}
Except you should never write such broad styling like that. I do not want all videos on the site center-aligned on the page, only these ones. I should be able to choose what videos have what alignment.
To that end, I resorted to JavaScript to resolve the issue (despite there already being a ton of JavaScript on the site from the theme). I started by adding a paragraph tag with the class video-center before the shortcode.
<!-- When rendered, the DOM structure will be:
<p class="video-center"></p>
<div class="wp-video"> ... </div>
It must be a paragraph rather than a more ideal element (span) because
WordPress automatically wraps every non p, a, or h1-h6 tag in a paragraph,
which breaks the desired DOM structure.
-->
<p class="video-center"></p>[video width="1280" height="720" mp4="http://www.example.com/wp-content/uploads/2016/03/promo-video.mp4"][/video]
In this way, I can selectively choose what videos I want to be centered. I then load the following JS on each page:
// Use querySelectorAll so multiple videos on a page can be aligned
var vidCenter = document.querySelectorAll(".video-center");
// Make sure we have at least one center element
if (vidCenter) {
// Beacause querySelectorAll returns an array-like NodeList
// instead of a proper array, we have to use a for-loop instead
// of the more ideal forEach method. This can be worked around
// but it's useless for such trivial code.
for (var i = 0; i < vidCenter.length; i++) {
// Check if the next sibling element is the embedded video
if (vidCenter[i].nextSibling.classList.contains("wp-video")) {
// Select the video and apply the margin-centering rules
var video = vidCenter[i].nextSibling;
video.style.marginRight = "auto";
video.style.marginLeft = "auto";
}
}
}
The comments explain everything, but of note is the nextSibling attribute. It is what selects the embed video.
Of course, this could be done as well with CSS:
/* In this case, the + selector is the same as nextSibling */
.video-center + .wp-video {
margin-right: auto;
margin-left: auto;
}
I've chosen JS for now as it was a tad easier to side-load it, but I'll likely switch to CSS soon.
And that is how not to go about centering a wrapper div. This whole post and issue could have avoided if WordPress just allowed the right way to do it (add a class to the wrapper div via the shortcode and/or support video alignment), but nope. Hopefully you have learned something through all this.