0

PROBLEM: When placing the div associated with the button, the wpautop function encapsulates the surrounding obects in up to 2 p tags which add up to 2 empty lines in the ouput (1 line above the div and/or 1 line under the div).

All these empty lines are both ugly to see and worsen the fruition of the site, hence I want to get rid of them in a proper way.

EDIT: Here is the DEMO whose output is equal to what I see on my localhost wordpress site.

I'm working on a collapsible button (button+div) that can be placed inline, such that more than one button can be placed in the same line. The content is hidden in a div and can be shown by clicking on the button, then it can be re-hidden by clicking again on the button.

Since the div is an inline-block element, when placed in the text it usually moves the surrounding objects. In particular in wordpress, when a div is placed inside a text (which is originally contained in a single p tag), the texts above and below it are automatically (by wpautop function) placed inside two separate p tags. As a consequence, the div will have a blank line (of height 1em) above and beyond, as shown in the following image

enter image description here

What I would like to obatin is instead a collapsible button that doesn't move up or down the surrounding text/objects.

We can say that I actually achieved the goal, but I had to introduce 4 classes to style the divs in various contexts, and as we will see soon, this led to a messy system which is neither user friendly nor easy to remember.

Here is the snippet code (CSS+JS) of the collapsible button.

(I will not use snippet codes in the examples below since the div there behaves differently from wordpress: in fact when using snippets the text above and below a div is not placed inside two p tags.)

1. Buttons in non-spaced lines

Let's continue the previous example, add a button and its content inside a div

text
text <button class="col">button</button> text
<div class="con">content</div>
text
text

enter image description here

In order to avoid the empty lines we have to style the div obejct

text
text <button class="col">button</button> text
<div class="con" style="margin: -1em 0 -1em;">content</div>
text
text

enter image description here

But if we add another button in the same line, we have to style its associated div slightly differently

text
text <button class="col">btn1</button> text <button class="col">btn2</button> text
<div class="con" style="margin: -1em 0 -1em;">content1</div>
<div class="con" style="margin: 1em 0 -1em;">content2</div>
text
text

enter image description here

If we add more buttons in the same line, the associated divs have to be styled like the second one.

2. Buttons in spaced lines

Consider now the case enter image description here. In order to keep the space between the lines we have to add a new style for the first div, while the second one doesn't require any style.

text

text <button class="col">btn1</button> text <button class="col">btn2</button> text
<div class="con" style="margin-top: -1em">content1</div>
<div class="con">content2</div>

text

enter image description here

If we add more buttons in the same line, we have not to style their associated divs.

3. Buttons before a ul list

Consider the case enter image description here. This case is equivalent to case 2, in fact we have to use the same styles.

text <button class="col">btn1</button> text <button class="col">btn2</button> text
<div class="con" style="margin-top: -1em;">content1</div>
<div class="con">content2</div>
<ul>
     <li>text</li>
     <li>text</li>
</ul>
text

enter image description here

4. Buttons inside a ul list

Consider the case enter image description here. In order to keep the space between the first and third elements, we have not to style the divs.

text
<ul>
    <li>text</li>
    <li>text <button class="col">btn1</button> text <button class="col">btn2</button> text
        <div class="con">content1</div>
        <div class="con">content2</div></li>
    <li>text</li>
</ul>
text

enter image description here

Consider now the case enter image description here. In order to keep the space between the buttons we have to

  • FIRST LINE: add a new class for the first div, use one of the previous style for the following divs (specifically, the second style that we saw in the first example)
  • MID LINES: use the same styles as in the first example
  • LAST LINE: use one of the previous style for the first div (specifically, the first style we saw in the second example)

.

text
<ul>
    <li>text</li>
    <li>text <button class="col">btn1</button> text <button class="col">btn2</button> text
        <div class="con" style="margin-bottom: -1em;">content1</div>
        <div class="con" style="margin-top: 1em; margin-bottom: -1em;">content2</div>
        text <button class="col">btn3</button> text <button class="col">btn4</button> text
        <div class="con" style="margin-top: -1em; margin-bottom: -1em;">content3</div>
        <div class="con" style="margin-top: 1em; margin-bottom: -1em;">content4</div>
        text <button class="col">btn5</button> text <button class="col">btn6</button> text
        <div class="con" style="margin-top: -1em;">content5</div>
        <div class="con">content6</div></li>
    <li>text</li>
</ul>
text

enter image description here

Summary

By defining each style in a separate css class we can lighten the code, here are the class names I chose:

  • nop: it is a contraction of "no p paragraphs", since the goal is to cancel the spacing due to the paragraphs created after the placing of a div
  • nop_next: to be used in the divs following the first one
  • nop_spaced: to be used in the first div in spaced lines
  • nop_ul: to be used only in the lists (ul/ol)

Here are all the previous examples in a single code

text
text <button class="col">btn1</button> text <button class="col">btn2</button> text
<div class="con nop">content1</div>
<div class="con nop_next">content2</div>
text

text <button class="col">btn3</button> text <button class="col">btn4</button> text
<div class="con nop_spaced">content3</div>
<div class="con">content4</div>

text
text <button class="col">btn5</button> text <button class="col">btn6</button> text
<div class="con nop_spaced">content5</div>
<div class="con">content6</div>
<ul>
     <li>text</li>
     <li>text</li>
</ul>
text
<ul>
    <li>text</li>
    <li>text <button class="col">btn7</button> text <button class="col">btn8</button> text
        <div class="con">content7</div>
        <div class="con">content8</div></li>
    <li>text</li>
    <li>text <button class="col">btn9</button> text <button class="col">btn10</button> text
        <div class="con nop_ul">content9</div>
        <div class="con nop_next">content10</div>
        text <button class="col">btn11</button> text <button class="col">btn12</button> text
        <div class="con nop">content11</div>
        <div class="con nop_next">content12</div>
        text <button class="col">btn13</button> text <button class="col">btn14</button> text
        <div class="con nop_spaced">content13</div>
        <div class="con">content14</div></li>
    <li>text</li>
</ul>
text

enter image description here

Disabling wpautop

By disabling the wpautop built-in function, no more p paragraphs are created when divs are placed in the text, hence there is no need to style the divs.

As a big side effect, by disabling wpautop all the paragraphs p and line breaks br which are automatically added have to be manually added. Sometimes the time needed to manually add them is even more than the time needed to correctly style the divs of the buttons, moreover sometimes by manually adding a p tag an unwanted space is created so to cancel it is necessary to add CSS code (which is exactly what we wanted to avoid by chosing to disable wpautop) or to add br tags instead (which not always precisely add the wanted space).

This is the code that we have to write, with wpautop disabled, in order to have an almost identical ouput ("almost" because in certain places br tags have to be used instead of p tags, and br not always generate the same height as p).

(edits to the previous code are marked with %% (if the output of the edit is identical) or %%%% (if the output of the edit is not identical))

<br>text<br> %%%%
text <button class="col">btn1</button> text <button class="col">btn2</button> text
<div class="con">content1</div>
<div class="con">content2</div>
text<br><br> %%%%

text <button class="col">btn3</button> text <button class="col">btn4</button> text
<div class="con">content3</div>
<div class="con">content4</div>

<br>text<br> %%
text <button class="col">btn5</button> text <button class="col">btn6</button> text
<div class="con">content5</div>
<div class="con">content6</div>
<ul>
     <li>item</li>
</ul>
text
<ul>
    <li>text</li>
    <li>text <button class="col">btn7</button> text <button class="col">btn8</button> text
        <div class="con">content7</div>
        <div class="con">content8</div></li>
    <li>text</li>
    <li>text <button class="col">btn9</button> text <button class="col">btn10</button> text
        <div class="con">content9</div>
        <div class="con">content10</div>
        text <button class="col">btn11</button> text <button class="col">btn12</button> text
        <div class="con">content11</div>
        <div class="con">content12</div>
        text <button class="col">btn13</button> text <button class="col">btn14</button> text
        <div class="con">content13</div>
        <div class="con">content14</div></li>
    <li>text</li>
</ul>
<p>text</p> %%

enter image description here

and from this zoomed particulars it can be seen that

  • The space above the first line is different
  • The space between lines 3 and 4 is different
  • The space between lines 4 and 5 is different

enter image description here

Conclusion

To achieve the initial goal we introduced 4 CSS classes to style the divs associated with the buttons in various (but no all) contexts. Since the examples seen here don't cover all the possibile cases, I'm sure that more styling classes have to be added.

I'm not a programmer so I don't know which are the usual techniques used in cases like this (introducing an HTML object which has to comply with some spacing rules), but to me the "classes solution" is not very practical. Moreover, disabling wpautop is not always a good solution as we seen.

I wonder, how does a web designer approach and solve this problem?

  • This is a really long question with lots of code and possible solutions, but I'm unsure what the problem/original task you were trying to do was, and thus what the problem is, but if I take the first paragraph, are you basically asking how to do an accordion UI? Keep in mind that frontend questions about JS/CSS aren't WP questions, and are offtopic, and should be asked on stackoverflow. Remember this isn't a discussion forum/Bulletin board, it's a Q/A site, you need to ask a clear and specific question that can be concretely answered and marked as the correct answer – Tom J Nowell Oct 25 '19 at 17:00
  • Read the first example to understand. Basically, when placing in the text the div associated with the button, the wpautop function creates (usually) 2 p tags which add two empty lines in the ouput (1 line above the div and 1 line under the div). If the div is placed inside a ul list then there are other possibile results (no empty lines added or 1 empty line added above or 1 empty line added below or 1 empty line added above and 1 below). All these empty lines are both ugly to see and worsen the fruition of the site. Hence I want to get rid of them in a proper way. – sound wave Oct 25 '19 at 17:10
  • Have you considered creating a block or a shortcode? They would allow you to create your preferred HTML structure, usually without injecting anything via wpautop. – WebElaine Oct 25 '19 at 17:12
  • 1
    @soundwave can you edit your question to include a clearly worded summary? This is a massive question that'll take a good 20 minutes to read through, and your comment explaining it has a lot of individual pieces to mentally track and visualise. I get the impression your entire question could probably be simplified to a 7 word sentence. Also, does the content have to use <br> tags? And do you have to put the raw tags you want to use inside the content as HTML markup rather than using shortcodes or blocks? Keep in mind what you want has ultra poor accessibility – Tom J Nowell Oct 25 '19 at 17:40
  • 1
    Also, the newlines in HTML shouldn't be showing unless you're setting CSS to display them, which it doesn't by default. A new line requires a closing </p> tag or a <br/>. Perhaps if you rewind back to the original problem that you were trying to solve and ask about that it might make more sense? Rather than asking how to fix the solution you've devised – Tom J Nowell Oct 25 '19 at 17:42
0

To solve the problem we have to use the adjacent selector + and shortcodes.

With the adjacent selector we target any .con after a p, any p after a .con. and any br after a div.

p + .con { margin-top: -1em; }
.con + p { margin-top: 0; }
div + br { display: none; }

Then we define a shortcode for each <div class=con>...</div>. If the content of each div is a shortcode we can do the job with a loop

$shortcodes = array('...','...',...);
foreach ($shortcodes as $name) {
    add_shortcode( $name, function ( $atts ) use ( $name ) {
        remove_filter( 'the_content', 'wpautop' );
        $content = apply_filters( 'the_content', '<div class=con>[block name=' . $name . ']</div>' );
        add_filter( 'the_content', 'wpautop' );
        return $content;
    });
}

otherwise we use the usual way

function scname_sc( $atts ) {
    remove_filter( 'the_content', 'wpautop' );
    $content = apply_filters( 'the_content', '<div class=con>...</div>' );
    add_filter( 'the_content', 'wpautop' );
    return $content;
}
add_shortcode( 'scname', 'scname_sc' );

Finally we can obtain the desired output by writing

text
text <button class="col">btn1</button> text <button class="col">btn2</button> text
[...][...]
text

text <button class="col">btn3</button> text <button class="col">btn4</button> text
[...][...]

text
text <button class="col">btn5</button> text <button class="col">btn6</button> text
[...][...]
<ul>
     <li>text</li>
     <li>text</li>
</ul>
text
<ul>
    <li>text</li>
    <li>text <button class="col">btn7</button> text <button class="col">btn8</button> text
        [...][...]</li>
    <li>text</li>
    <li>text <button class="col">btn9</button> text <button class="col">btn10</button> text
        [...][...]
        text <button class="col">btn11</button> text <button class="col">btn12</button> text
        [...][...]
        text <button class="col">btn13</button> text <button class="col">btn14</button> text
        [...][...]</li>
    <li>text</li>
</ul>
text

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.