diff --git a/devops/scripts/benchmarks/html/scripts.js b/devops/scripts/benchmarks/html/scripts.js
index 6f0bec617ceb1..0a06c9bfee7a0 100644
--- a/devops/scripts/benchmarks/html/scripts.js
+++ b/devops/scripts/benchmarks/html/scripts.js
@@ -123,8 +123,10 @@ function createChart(data, containerId, type) {
}
const ctx = document.getElementById(containerId).getContext('2d');
+
const options = {
responsive: true,
+ maintainAspectRatio: false,
plugins: {
title: {
display: true,
@@ -157,6 +159,13 @@ function createChart(data, containerId, type) {
}
}
},
+ legend: {
+ position: 'top',
+ labels: {
+ boxWidth: 12,
+ padding: 10,
+ }
+ },
annotation: type === 'time' ? {
annotations: {}
} : undefined
@@ -227,6 +236,32 @@ function createChart(data, containerId, type) {
const chart = new Chart(ctx, chartConfig);
chartInstances.set(containerId, chart);
+ // Set explicit canvas size after chart creation to ensure proper sizing
+ const canvas = document.getElementById(containerId);
+ const rect = canvas.getBoundingClientRect();
+ const dpr = window.devicePixelRatio || 1;
+
+ // Calculate dynamic height based on number of legend items
+ const legendItemCount = type === 'time' ?
+ Object.values(data.runs).length :
+ data.datasets.length;
+
+ // Base chart height + legend height (25px per line + padding)
+ const baseChartHeight = 350;
+ const legendHeight = Math.max(legendItemCount * 25, 50); // minimum 50px for legend
+ const totalHeight = baseChartHeight + legendHeight;
+
+ // Set canvas dimensions for crisp rendering
+ canvas.width = rect.width * dpr;
+ canvas.height = totalHeight * dpr;
+
+ // Scale the context to ensure correct drawing operations
+ const context = canvas.getContext('2d');
+ context.scale(dpr, dpr);
+
+ // Force chart to use these exact dimensions
+ chart.resize(rect.width, totalHeight);
+
// Add annotation interaction handlers for time-series charts
if (type === 'time') {
ChartAnnotations.setupAnnotationListeners(chart, ctx, options);
@@ -306,6 +341,10 @@ function createChartContainer(data, canvasId, type) {
container.setAttribute('data-label', data.label);
container.setAttribute('data-suite', data.suite);
+ // Create header section for metadata
+ const headerSection = document.createElement('div');
+ headerSection.className = 'chart-header';
+
// Check if this benchmark is marked as unstable
const metadata = metadataForLabel(data.label, type);
if (metadata && metadata.unstable) {
@@ -316,15 +355,17 @@ function createChartContainer(data, canvasId, type) {
unstableWarning.className = 'benchmark-unstable';
unstableWarning.textContent = metadata.unstable;
unstableWarning.style.display = isUnstableEnabled() ? 'block' : 'none';
- container.appendChild(unstableWarning);
+ unstableWarning.style.marginBottom = '5px';
+ headerSection.appendChild(unstableWarning);
}
- // Add description if present in metadata (moved outside of details)
+ // Add description if present in metadata
if (metadata && metadata.description) {
const descElement = document.createElement('div');
descElement.className = 'benchmark-description';
descElement.textContent = metadata.description;
- container.appendChild(descElement);
+ descElement.style.marginBottom = '5px';
+ headerSection.appendChild(descElement);
}
// Add notes if present
@@ -333,7 +374,7 @@ function createChartContainer(data, canvasId, type) {
noteElement.className = 'benchmark-note';
noteElement.textContent = metadata.notes;
noteElement.style.display = isNotesEnabled() ? 'block' : 'none';
- container.appendChild(noteElement);
+ headerSection.appendChild(noteElement);
}
// Add tags if present
@@ -358,12 +399,31 @@ function createChartContainer(data, canvasId, type) {
tagsContainer.appendChild(tagElement);
});
- container.appendChild(tagsContainer);
+ headerSection.appendChild(tagsContainer);
}
+ // Add header section to container
+ container.appendChild(headerSection);
+
+ // Create main content section (chart + legend area)
+ const contentSection = document.createElement('div');
+ contentSection.className = 'chart-content';
+
+ // Canvas for the chart - fixed position in content flow
const canvas = document.createElement('canvas');
canvas.id = canvasId;
- container.appendChild(canvas);
+ canvas.style.width = '100%';
+
+ // Set a default height - will be properly sized later in createChart
+ canvas.style.height = '400px';
+ canvas.style.marginBottom = '10px';
+ contentSection.appendChild(canvas);
+
+ container.appendChild(contentSection);
+
+ // Create footer section for details
+ const footerSection = document.createElement('div');
+ footerSection.className = 'chart-footer';
// Create details section for extra info
const details = document.createElement('details');
@@ -387,7 +447,8 @@ function createChartContainer(data, canvasId, type) {
extraInfo.innerHTML = generateExtraInfo(data, 'benchmark');
details.appendChild(extraInfo);
- container.appendChild(details);
+ footerSection.appendChild(details);
+ container.appendChild(footerSection);
return container;
}
diff --git a/devops/scripts/benchmarks/html/styles.css b/devops/scripts/benchmarks/html/styles.css
index 3e9c3bd22fc37..5a07f834c9415 100644
--- a/devops/scripts/benchmarks/html/styles.css
+++ b/devops/scripts/benchmarks/html/styles.css
@@ -18,8 +18,24 @@ h1, h2 {
background: white;
border-radius: 8px;
padding: 24px;
- margin-bottom: 24px;
- box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ box-sizing: border-box;
+ min-height: fit-content;
+ margin: 10px 0;
+ overflow: visible;
+}
+.chart-header {
+ padding: 10px;
+ border-radius: 6px 6px 0 0;
+}
+.chart-content {
+ padding: 10px;
+ display: flex;
+ flex-direction: column;
+ min-height: fit-content;
}
@media (max-width: 768px) {
body {