html5 <summary> element with some text right justified

半世苍凉 提交于 2019-12-23 16:06:12

问题


I am trying to use html5's <details> and <summary> elements to present a collapsible/expandable outline-style list but can't figure out how to get the <summary> element text formatted correctly.

I want the text left justified and the timestamp and block of links right justified. I tried to do this by using a flexbox for the line and doing the layout inside the flexbox. This works fine for the text in the <details> part.

However, on the summary line everything I've tried results in either the text being properly formatted (like the details text) but on a line below the triangle, or on the same line as the triangle, but with everything left justified.

Here is a snippet of showing the summary text formatted correctly but on a new line.

.outline { background-color: #e0e0ff; margin: 30px; }
      /* Styling on <details> and <summary> below provides
         indentation for nested details blocks. */
    details > *:not(summary) { margin-left: 1em; }
    summary { display: list-item; }
    .title { display: flex; }
    .bsect { display: flex; }
    .ttext, .ts, .actions, .btext { border: 1px solid green; }
    .ttext, .btext { flex: 1; }
    .ts, .actions  { flex: 0; white-space:nowrap; }
    pre  { white-space: pre-wrap; margin: 0; font-size: 12pt }
<div class="outline">
    <details id="b5750h35">
      <summary>
        <div class="title">
          <div class="ttext">A short title </div>
          <div class="ts">2018-07-05 12:00</div>
          <div class="actions">
            <a href="#">L1</a>
            <a href="#">L2</a>
            </div>
          </div>
        </summary>
      <!-- Following the summary are zero or more intermixed
           bsect and detail blocks -->
      <div id="b5750c32" class="bsect"><!--flex container-->
        <pre class="btext">Some multi-line
 body text.</pre>
        <div class="ts">2018-07-05 12:00</div>
        <div class="actions">
          <a href="#">L1</a>
          <a href="#">L2</a>
          </div>
        <!--more bsects or details go here -->
        </div><!--id="b5750c32"-->
      </details><!-- id="b5750h35" -->

    </div>

Changing the .title { display: flex; } to .title { display: inline-flex; } shows the other result (text on same line as triangle but everything left-justified; can gets the same result using <spans>s instead of <div>s):

    .outline { background-color: #e0e0ff; margin: 30px; }
      /* Styling on <details> and <summary> below provides
         indentation for nested details blocks. */
    details > *:not(summary) { margin-left: 1em; }
    summary { display: list-item; }
    .title { display: inline-flex; }
    .bsect { display: flex; }
    .ttext, .ts, .actions, .btext { border: 1px solid green; }
    .ttext, .btext { flex: 1; }
    .ts, .actions  { flex: 0; white-space:nowrap; }
    pre  { white-space: pre-wrap; margin: 0; font-size: 12pt }
  <div class="outline">
    <details id="b5750h35">
      <summary>
        <div class="title">
          <div class="ttext">A short title </div>
          <div class="ts">2018-07-05 12:00</div>
          <div class="actions">
            <a href="#">L1</a>
            <a href="#">L2</a>
            </div>
          </div>
        </summary>
      <!-- Following the summary are zero or more intermixed
           bsect and detail blocks -->
      <div id="b5750c32" class="bsect"><!--flex container-->
        <pre class="btext">Some multi-line
 body text.</pre>
        <div class="ts">2018-07-05 12:00</div>
        <div class="actions">
          <a href="#">L1</a>
          <a href="#">L2</a>
          </div>
        <!--more bsects or details go here -->
        </div><!--id="b5750c32"-->
      </details><!-- id="b5750h35" -->

    </div>

What magic is needed to get the properly formatted text on the same line as the triangle? I'd prefer a simple solution that continues to use flexbox if possible but if some other approach to achieving the wanted results is better, that's fine too.


回答1:


This is how I'd do it:

summary {
  display: flex;
  align-items: center; /* added this to center the arrow. optional */
}
summary .title {
  flex-grow: 1;
}

.outline { background-color: #e0e0ff; margin: 30px; }
      /* Styling on <details> and <summary> below provides
         indentation for nested details blocks. */
    details > *:not(summary) { margin-left: 1em; }
    summary { display: list-item; }
    .title { display: inline-flex; }
    .bsect { display: flex; }
    .ttext, .ts, .actions, .btext { border: 1px solid green; }
    .ttext, .btext { flex: 1; }
    .ts, .actions  { flex: 0; white-space:nowrap; }
    pre  { white-space: pre-wrap; margin: 0; font-size: 12pt }
    
summary {
  display: flex;
  align-items: center;
}
summary .title {
  flex-grow: 1;
}
<div class="outline">
    <details id="b5750h35">
      <summary>
        <div class="title">
          <div class="ttext">A short title </div>
          <div class="ts">2018-07-05 12:00</div>
          <div class="actions">
            <a href="#">L1</a>
            <a href="#">L2</a>
            </div>
          </div>
        </summary>
      <!-- Following the summary are zero or more intermixed
           bsect and detail blocks -->
      <div id="b5750c32" class="bsect"><!--flex container-->
        <pre class="btext">Some multi-line
 body text.</pre>
        <div class="ts">2018-07-05 12:00</div>
        <div class="actions">
          <a href="#">L1</a>
          <a href="#">L2</a>
          </div>
        <!--more bsects or details go here -->
        </div><!--id="b5750c32"-->
      </details><!-- id="b5750h35" -->

    </div>

As alohci pointed out, in FF the arrow is not displayed unless summary has display:list-item.

One way to make it work with display:list-item is using floats:

.title, .bsect {
   width: calc(100% - 1.08em);
   float: right;
}
details {
  overflow: hidden;
}

.outline { background-color: #e0e0ff; margin: 30px; }
      /* Styling on <details> and <summary> below provides
         indentation for nested details blocks. */
    details > *:not(summary) { margin-left: 1em; }
    summary { display: list-item; }
    .title { display: inline-flex; }
    .bsect { display: flex; }
    .ttext, .ts, .actions, .btext { border: 1px solid green; }
    .ttext, .btext { flex: 1; }
    .ts, .actions  { flex: 0; white-space:nowrap; }
    pre  { white-space: pre-wrap; margin: 0; font-size: 12pt }
    
.title, .bsect {
   width: calc(100% - 1.08em);
   float: right;
}
details {
  overflow: hidden;
}
<div class="outline">
    <details id="b5750h35">
      <summary>
        <div class="title">
          <div class="ttext">A short title </div>
          <div class="ts">2018-07-05 12:00</div>
          <div class="actions">
            <a href="#">L1</a>
            <a href="#">L2</a>
            </div>
          </div>
        </summary>
      <!-- Following the summary are zero or more intermixed
           bsect and detail blocks -->
      <div id="b5750c32" class="bsect"><!--flex container-->
        <pre class="btext">Some multi-line
 body text.</pre>
        <div class="ts">2018-07-05 12:00</div>
        <div class="actions">
          <a href="#">L1</a>
          <a href="#">L2</a>
          </div>
        <!--more bsects or details go here -->
        </div><!--id="b5750c32"-->
      </details><!-- id="b5750h35" -->

    </div>

Not as neat and clean as flexbox, but does work.




回答2:


Make the summary a flex container then add flex:1 to .title to make it fit all the space:

.outline { background-color: #e0e0ff; margin: 30px; }
      /* Styling on <details> and <summary> below provides
         indentation for nested details blocks. */
    details > *:not(summary) { margin-left: 1em; }
    .title { display: flex; }
    .bsect { display: flex; }
    .ttext, .ts, .actions, .btext { border: 1px solid green; }
    .ttext, .btext { flex: 1; }
    .ts, .actions  { flex: 0; white-space:nowrap; }
    pre  { white-space: pre-wrap; margin: 0; font-size: 12pt }
    
 summary {
   display: flex;
   align-items:center;
 }
 summary > .title {
  flex:1;
 }
<div class="outline">
    <details id="b5750h35">
      <summary>
        <div class="title">
          <div class="ttext">A short title </div>
          <div class="ts">2018-07-05 12:00</div>
          <div class="actions">
            <a href="#">L1</a>
            <a href="#">L2</a>
            </div>
          </div>
        </summary>
      <!-- Following the summary are zero or more intermixed
           bsect and detail blocks -->
      <div id="b5750c32" class="bsect"><!--flex container-->
        <pre class="btext">Some multi-line
 body text.</pre>
        <div class="ts">2018-07-05 12:00</div>
        <div class="actions">
          <a href="#">L1</a>
          <a href="#">L2</a>
          </div>
        <!--more bsects or details go here -->
        </div><!--id="b5750c32"-->
      </details><!-- id="b5750h35" -->

    </div>

UPDATE

For Firefox you can consider adding width to the inline-flex element. We can consider em unit to make it working with any font-size:

.outline {
  background-color: #e0e0ff;
  margin: 30px;
}

details>*:not(summary) {
  margin-left: 1em;
}

.title {
  display: inline-flex;
}

.bsect {
  display: flex;
}

.ttext,
.ts,
.actions,
.btext {
  border: 1px solid green;
}

.ttext,
.btext {
  flex: 1;
}

.ts,
.actions {
  flex: 0;
  white-space: nowrap;
}

pre {
  white-space: pre-wrap;
  margin: 0;
  font-size: 12pt
}

summary>.title {
  width: calc(100% - 1.1em);
  margin-left: -0.3em;
}
<div class="outline">
  <details id="b5750h35">
    <summary>
      <div class="title">
        <div class="ttext">A short title </div>
        <div class="ts">2018-07-05 12:00</div>
        <div class="actions">
          <a href="#">L1</a>
          <a href="#">L2</a>
        </div>
      </div>
    </summary>
    <!-- Following the summary are zero or more intermixed
           bsect and detail blocks -->
    <div id="b5750c32" class="bsect">
      <!--flex container-->
      <pre class="btext">Some multi-line
 body text.</pre>
      <div class="ts">2018-07-05 12:00</div>
      <div class="actions">
        <a href="#">L1</a>
        <a href="#">L2</a>
      </div>
      <!--more bsects or details go here -->
    </div>
    <!--id="b5750c32"-->
  </details>
  <!-- id="b5750h35" -->

</div>

<div class="outline" style="font-size:25px;">
  <details id="b5750h35">
    <summary>
      <div class="title">
        <div class="ttext">A short title </div>
        <div class="ts">2018-07-05 12:00</div>
        <div class="actions">
          <a href="#">L1</a>
          <a href="#">L2</a>
        </div>
      </div>
    </summary>
    <!-- Following the summary are zero or more intermixed
           bsect and detail blocks -->
    <div id="b5750c32" class="bsect">
      <!--flex container-->
      <pre class="btext">Some multi-line
 body text.</pre>
      <div class="ts">2018-07-05 12:00</div>
      <div class="actions">
        <a href="#">L1</a>
        <a href="#">L2</a>
      </div>
      <!--more bsects or details go here -->
    </div>
    <!--id="b5750c32"-->
  </details>
  <!-- id="b5750h35" -->

</div>


来源:https://stackoverflow.com/questions/52583004/html5-summary-element-with-some-text-right-justified

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!