Quellcode durchsuchen

Flexbox: Apply automatic minimum size of flex items in column mode with auto size, see #658

This better conforms to CSS specs in such situations, please the in-line comments and the linked issue.

Added visual tests to test related designs, and where this change makes a difference.
Michael Ragazzon vor 1 Jahr
Ursprung
Commit
b6113b3acd

+ 6 - 0
Source/Core/Layout/FlexFormattingContext.cpp

@@ -366,6 +366,12 @@ void FlexFormattingContext::Format(Vector2f& flex_resulting_content_size, Vector
 			FormattingContext::FormatIndependent(flex_container_box, element, (format_box.GetSize().x >= 0 ? &format_box : nullptr),
 				FormattingContextType::Block);
 			item.inner_flex_base_size = element->GetBox().GetSize().y;
+
+			// Apply the automatic block size as minimum size (§4.5). Strictly speaking, we should also apply this to
+			// the other branches in column mode (and inline min-content size in row mode). However, the formatting step
+			// can be expensive, here we have already done that step so the value is readily accessible to us.
+			if (item.main.min_size == 0.f && !LayoutDetails::IsScrollContainer(computed.overflow_x(), computed.overflow_y()))
+				item.main.min_size = Math::Min(item.inner_flex_base_size, item.main.max_size);
 		}
 
 		// Calculate the hypothetical main size (clamped flex base size).

+ 217 - 0
Tests/Data/VisualTests/flex_06.rml

@@ -0,0 +1,217 @@
+<rml>
+<head>
+	<title>Flex 06 - Player list</title>
+	<link type="text/rcss" href="../style.rcss"/>
+	<link rel="match" href="reference/flex_06-ref.rml"/>
+	<link rel="help" href="https://drafts.csswg.org/css-flexbox/" />
+	<link rel="#658" href="https://github.com/mikke89/RmlUi/issues/658" />
+	<meta name="Description" content="Flex container in column mode with an auto-sized header and footer. Their automatic minimum size should exactly fit their contents. The players list in the middle has auto overflow, and thus should not have automatic minimum sizing applied." />
+	<style>
+		body {
+			box-sizing: border-box;
+			height: 50%;
+			top: 20%;
+			left: 12dp;
+			min-width: 450dp;
+			min-height: 250dp;
+			padding: 30dp 0 0 0;
+			border: 1px #a0a0a0;
+		}
+
+		scrollbarvertical sliderbar, scrollbarvertical slidertrack {
+			border-width: 0;
+		}
+
+		handle#title {
+			width: auto;
+			height: auto;
+			display: block;
+			top: 0;
+			right: 0;
+			left: 0;
+			bottom: auto;
+			cursor: move;
+			background-color: #a0a0a0;
+			padding: 5dp 20dp;
+			font-weight: bold;
+			font-size: 1.25em;
+		}
+
+		handle#resizer {
+			width: 12dp;
+			height: 12dp;
+			background: #a0a0a0;
+		}
+
+		input.text {
+			box-sizing: border-box;
+			width: 100%;
+			padding: 10dp;
+			border: 1dp #bbb;
+			border-radius: 3dp;
+			font-size: 1.1em;
+			line-height: 1.4;
+			cursor: text;
+		}
+
+		#contents {
+			display: flex;
+			flex-direction: column;
+			box-sizing: border-box;
+			height: 100%;
+			padding: 20dp;
+		}
+
+		#panel_info {
+			/*flex: none;*/
+			display: flex;
+			justify-content: space-between;
+			font-size: .95em;
+		}
+
+		#players {
+			/*flex: 1;*/
+			margin: 15dp 0;
+			overflow: auto;
+			border: 1px #bbb;
+		}
+
+		#footer {
+			/*flex: none;*/
+		}
+
+		table thead tr {
+			font-weight: bold;
+			padding-bottom: 1dp;
+		}
+
+		table td {
+			padding: 14dp 4dp;
+		}
+
+		table td.data_column {
+			width: 70dp;
+			text-align: center;
+		}
+
+		table tbody td.data_column {
+			font-size: .9em;
+		}
+
+		table td.tag_column {
+			width: 90dp;
+		}
+	</style>
+</head>
+
+<body>
+<handle id="title" move_target="#document">Player List</handle>
+
+<div id="contents">
+	<div id="panel_info">
+		<div>Server: Europe #56763</div>
+		<div>Players: 99</div>
+	</div>
+
+	<div id="players">
+		<table>
+			<thead>
+			<tr>
+				<td class="data_column">ID</td>
+				<td class="tag_column">Player Tag</td>
+				<td></td>
+				<td class="data_column">Ping</td>
+				<td class="data_column">Score</td>
+			</tr>
+			</thead>
+
+			<tbody>
+			<tr>
+				<td class="data_column">10</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">11</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">12</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">13</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">14</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">15</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">16</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">17</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">18</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">19</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">20</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			</tbody>
+		</table>
+	</div>
+
+	<div id="footer">
+		<input type="text"/>
+	</div>
+</div>
+
+<handle size_target="#document" id="resizer"/>
+</body>
+</rml>

+ 4 - 1
Tests/Data/VisualTests/issue_452_scrollbar_resets.rml

@@ -31,10 +31,13 @@
 			border: 1px white;
 		}
 
+		.container > * {
+			overflow-y: auto;
+		}
+
 		.list {
 			display: block;
 			height: 100%;
-			overflow-y: auto;
 		}
 
 		.list > div {

+ 214 - 0
Tests/Data/VisualTests/reference/flex_06-ref.rml

@@ -0,0 +1,214 @@
+<rml>
+<head>
+	<title>Flex 06 - Player list</title>
+	<link type="text/rcss" href="../../style.rcss"/>
+	<meta name="Reference" content="The reference is also implemented using flexbox. However, the header and footer is explicitly set to 'flex: none', so that their size is always fixed. The player list uses 'flex: 1' so that it expands to the remaining available space. Being explicit like here is generally recommended practice, since it may avoid unnecessary content-based sizing which can impact performance." />
+	<style>
+		body {
+			box-sizing: border-box;
+			height: 50%;
+			top: 20%;
+			left: 55%;
+			min-width: 450dp;
+			min-height: 250dp;
+			padding: 30dp 0 0 0;
+			border: 1px #a0a0a0;
+		}
+
+		scrollbarvertical sliderbar, scrollbarvertical slidertrack {
+			border-width: 0;
+		}
+
+		handle#title {
+			width: auto;
+			height: auto;
+			display: block;
+			top: 0;
+			right: 0;
+			left: 0;
+			bottom: auto;
+			cursor: move;
+			background-color: #a0a0a0;
+			padding: 5dp 20dp;
+			font-weight: bold;
+			font-size: 1.25em;
+		}
+
+		handle#resizer {
+			width: 12dp;
+			height: 12dp;
+			background: #a0a0a0;
+		}
+
+		input.text {
+			box-sizing: border-box;
+			width: 100%;
+			padding: 10dp;
+			border: 1dp #bbb;
+			border-radius: 3dp;
+			font-size: 1.1em;
+			line-height: 1.4;
+			cursor: text;
+		}
+
+		#contents {
+			display: flex;
+			flex-direction: column;
+			box-sizing: border-box;
+			height: 100%;
+			padding: 20dp;
+		}
+
+		#panel_info {
+			flex: none;
+			display: flex;
+			justify-content: space-between;
+			font-size: .95em;
+		}
+
+		#players {
+			flex: 1;
+			margin: 15dp 0;
+			overflow: auto;
+			border: 1px #bbb;
+		}
+
+		#footer {
+			flex: none;
+		}
+
+		table thead tr {
+			font-weight: bold;
+			padding-bottom: 1dp;
+		}
+
+		table td {
+			padding: 14dp 4dp;
+		}
+
+		table td.data_column {
+			width: 70dp;
+			text-align: center;
+		}
+
+		table tbody td.data_column {
+			font-size: .9em;
+		}
+
+		table td.tag_column {
+			width: 90dp;
+		}
+	</style>
+</head>
+
+<body>
+<handle id="title" move_target="#document">Player List</handle>
+
+<div id="contents">
+	<div id="panel_info">
+		<div>Server: Europe #56763</div>
+		<div>Players: 99</div>
+	</div>
+
+	<div id="players">
+		<table>
+			<thead>
+			<tr>
+				<td class="data_column">ID</td>
+				<td class="tag_column">Player Tag</td>
+				<td></td>
+				<td class="data_column">Ping</td>
+				<td class="data_column">Score</td>
+			</tr>
+			</thead>
+
+			<tbody>
+			<tr>
+				<td class="data_column">10</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">11</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">12</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">13</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">14</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">15</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">16</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">17</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">18</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">19</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			<tr>
+				<td class="data_column">20</td>
+				<td>tag</td>
+				<td>Player name</td>
+				<td class="data_column">55 ms</td>
+				<td class="data_column">108</td>
+			</tr>
+			</tbody>
+		</table>
+	</div>
+
+	<div id="footer">
+		<input type="text"/>
+	</div>
+</div>
+
+<handle size_target="#document" id="resizer"/>
+</body>
+</rml>