问题
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