Created by: John Odlin
Date: 2025-01-15
Repository: https://github.com/panoramicdata/PanoramicData.Blazor
Branch: main
?? Bug / Technical Debt
PDFormBody component injects duplicate inline <style> tags causing CSS conflicts when multiple forms with different TitleWidth values exist on the same page
Medium (Affects UI consistency and maintainability)
Current version (prior to this fix)
Next release
- PanoramicData.Blazor
- PDFormBody Component
css, blazor, forms, technical-debt, ui-bug, multiple-forms, title-width
The PDFormBody component currently injects inline <style> tags into the DOM when the TitleWidth parameter is used. This causes CSS conflicts when multiple forms with different title widths exist on the same page, as the last rendered component's styles override all others globally.
When multiple PDFormBody components with different TitleWidth values are rendered:
<!-- From Form 1 with TitleWidth=200 -->
<style>.title-box { width: 200px }</style>
<div class="pd-form-body">
<div class="title-box">...</div>
</div>
<!-- From Form 2 with TitleWidth=300 -->
<style>.title-box { width: 300px }</style>
<div class="pd-form-body">
<div class="title-box">...</div>
</div>Result: The last rendered component wins (300px), overriding all other forms' title widths globally. Both forms end up with 300px title boxes.
Each form should maintain its own independent title width without affecting other forms on the same page:
- Form 1 should have 200px title boxes
- Form 2 should have 300px title boxes
This issue affects applications where:
- Multiple modal dialogs exist on a single page
- Different forms require different title widths
- Components from shared frameworks coexist with page-specific dialogs
Example: In MagicSuite applications (DataMagic, ReportMagic, AlertMagic):
- Organizations page has an EditDialog (needs 255px titles)
- The same page includes FeedbackUi from MagicSuite.Framework (needs 300px titles)
- Both forms incorrectly end up with the same width
Files Affected:
PanoramicData.Blazor/PDFormBody.razor- Contains inline<style>tagPanoramicData.Blazor/PDFormBody.razor.cs- ContainsWidthCssMarkuppropertyPanoramicData.Blazor/wwwroot/css/main.css- Missing CSS custom property rule
Problems:
- Global CSS Pollution: The
.title-boxclass is global, affecting ALL forms on the page - No Scoping: CSS class names have no component-specific identifier
- Performance: Multiple
<style>tags with duplicate/conflicting rules - Unpredictable Behavior: Render order determines which width "wins"
- Developer Confusion: Setting
TitleWidthappears to work initially but breaks when another form is added
PDFormBody.razor.cs:
private MarkupString WidthCssMarkup => new($".title-box {{ width: {TitleWidth}px }}");PDFormBody.razor:
<style>
@WidthCssMarkup
</style>
<div class="pd-form-body">
<!-- form content -->
</div>? Migrate from inline <style> tags to CSS custom properties (CSS variables) for proper scoping
- ? Proper scoping - each component has its own variable value
- ? No DOM pollution - no inline
<style>tags - ? Better performance - one CSS rule instead of N style tags
- ? Modern standards - widely supported in all modern browsers
- ? Maintainable - clean separation of concerns
- ? No breaking changes - API remains identical
File: PanoramicData.Blazor/wwwroot/css/main.css
Added:
/* PDFormBody - Support dynamic title widths using CSS custom properties */
.pd-form-body .title-box {
width: var(--title-width, 200px) !important;
min-width: var(--title-width, 200px) !important;
max-width: var(--title-width, 200px) !important;
flex: 0 0 var(--title-width, 200px) !important;
}Technical Details:
var(--title-width, 200px)- Uses CSS custom property with 200px fallback!important- Overrides Bootstrap's.input-group-textdefault stylesmin-width&max-width- Prevents flexbox from shrinking/growing the elementflex: 0 0 ...- Ensures element maintains size within flexbox containersflex-grow: 0- Don't grow to fill spaceflex-shrink: 0- Don't shrink if space is tightflex-basis: var(--title-width, 200px)- Use custom property as base size
File: PanoramicData.Blazor/PDFormBody.razor
Removed:
<style>
@WidthCssMarkup
</style>Changed:
<!-- Before -->
<div class="pd-form-body">
<!-- After -->
<div class="pd-form-body" style="@GetTitleWidthStyle()">File: PanoramicData.Blazor/PDFormBody.razor.cs
Removed:
private MarkupString WidthCssMarkup => new($".title-box {{ width: {TitleWidth}px }}");Added:
/// <summary>
/// Gets the inline style for setting the title width using CSS custom properties.
/// </summary>
private string GetTitleWidthStyle()
=> TitleWidth > 0
? $"--title-width: {TitleWidth}px;"
: string.Empty;Form 1 (TitleWidth=200):
<div class="pd-form-body" style="--title-width: 200px;">
<div class="title-box">First Name</div>
</div>Form 2 (TitleWidth=300):
<div class="pd-form-body" style="--title-width: 300px;">
<div class="title-box">First Name</div>
</div>Result: ? Each form has its own width, no conflicts!
File: PanoramicData.Blazor.Demo/Pages/FormTitleWidthTest.razor
Route: /form-title-width-test
Added to: Navigation menu (PanoramicData.Blazor.Demo/Shared/NavMenu.razor)
Test Page Features:
- Two side-by-side forms with different TitleWidth values (200px and 300px)
- Buttons to show each form in Create mode
- Uses
PersonDataProviderwithPersonmodel - Displays FirstName, LastName, and Email fields
| Scenario | Status | Description |
|---|---|---|
| Single form with TitleWidth | ? Pass | One form displays correct width |
| Multiple forms with same TitleWidth | ? Pass | Both forms display same width |
| Multiple forms with different TitleWidths | ? Pass | Each form maintains its own width |
| Forms nested in modals | ? Pass | Modal forms work correctly |
| Forms in different components | ? Pass | Component isolation works |
| Default TitleWidth (no parameter) | ? Pass | Uses 200px default from CSS |
| TitleWidth=0 | ? Pass | Uses 200px default from CSS |
| TitleWidth negative value | ?? Edge Case | Returns empty string (uses CSS default) |
CSS custom properties are supported in:
- ? Chrome 49+ (March 2016)
- ? Firefox 31+ (July 2014)
- ? Safari 9.1+ (March 2016)
- ? Edge 15+ (April 2017)
- ? All modern browsers used in enterprise environments
Note: Internet Explorer 11 does NOT support CSS custom properties, but IE11 is end-of-life (June 15, 2022) and not supported by .NET 9 Blazor applications.
? NONE - This is a non-breaking change:
- ? Public API remains identical (
TitleWidthparameter unchanged) - ? Default behavior unchanged (200px default)
- ? Existing code continues to work without modifications
- ? No migration required
| Benefit | Description |
|---|---|
| ?? No Conflicts | Each form instance maintains its own title width |
| ?? Better Performance | One CSS rule instead of N inline <style> tags |
| ?? Cleaner DOM | Eliminates inline style tag pollution |
| ?? Predictable Behavior | No "last one wins" conflicts |
| ?? No Workarounds Needed | Developers don't need :global() and !important hacks |
| ?? Modern Standards | Uses CSS best practices (custom properties) |
| ??? Maintainable | Clear pattern for future components |
?? Low Risk:
- Internal implementation change only
- Extensively tested across different scenarios
- Easy to rollback if issues arise
- CSS custom properties are widely supported in target browsers
- No changes to component's public interface
Location: README.md or inline XML comments
Add:
### TitleWidth Parameter
Sets the width of field title boxes using CSS custom properties.
**Type:** `int`
**Default:** `200`
**Example:**
```csharp
<PDFormBody TitleWidth="250" TItem="MyModel" />Note: Each form instance maintains its own title width, allowing multiple forms with different widths on the same page without conflicts.
Implementation: Uses CSS custom properties (--title-width) for scoping,
eliminating the need for inline <style> tags.
#### 2. CHANGELOG.md
**Add:**
```markdown
## [Version X.Y.Z] - 2025-01-XX
### Fixed
- **PDFormBody**: Fixed CSS conflicts when multiple forms with different `TitleWidth`
values exist on the same page. Migrated from inline `<style>` tags to CSS custom
properties for proper scoping. This is a non-breaking internal implementation change.
([#issue-number](https://github.com/panoramicdata/PanoramicData.Blazor/issues/XXX))
### Technical Details
- **Impact**: No breaking changes - existing code continues to work without modifications
- **Benefit**: Multiple forms with different title widths now work correctly on the same page
- **Performance**: Reduced DOM pollution from duplicate style tags
Create: docs/migration/title-width-fix.md
# PDFormBody TitleWidth Implementation Change
## Overview
The `TitleWidth` parameter implementation has been improved to use CSS custom properties
instead of inline `<style>` tags.
## Impact
? **No action required** - This is a non-breaking internal implementation change.
## Before (Problematic)
```html
<style>.title-box { width: 255px }</style>
<div class="pd-form-body">...</div><div class="pd-form-body" style="--title-width: 255px;">...</div>- Multiple forms with different title widths work correctly
- Cleaner DOM (no inline style tags)
- Better performance
- No CSS conflicts
None - your existing code will continue to work without any changes.
---
## Acceptance Criteria
### Functional Requirements
- [x] No inline `<style>` tags generated by PDFormBody component
- [x] Multiple forms with different `TitleWidth` values work correctly without conflicts
- [x] Each form maintains its specified title width independently
- [x] Default TitleWidth (200px) works when parameter not specified
- [x] TitleWidth=0 falls back to CSS default (200px)
### Technical Requirements
- [x] CSS custom property rule added to `main.css`
- [x] `GetTitleWidthStyle()` method implemented in `.razor.cs`
- [x] Inline `<style>` tag removed from `.razor` file
- [x] `WidthCssMarkup` property removed from `.razor.cs`
- [x] CSS properly handles Bootstrap flexbox context
- [x] `!important` flags used to override Bootstrap defaults
### Testing Requirements
- [x] Test page created demonstrating multiple forms
- [x] Test page added to navigation menu
- [x] Forms display correct widths when rendered side-by-side
- [x] No CSS conflicts observable in browser DevTools
- [x] Build succeeds without errors or warnings
### Code Quality
- [x] No new compiler warnings introduced
- [x] Code follows existing project patterns
- [x] XML documentation added to new method
- [x] No breaking changes to public API
---
## Verification Steps
### For Developer/Reviewer
1. **Stop** current debug session (if running)
2. **Rebuild** the solution (Build ? Rebuild Solution)
3. **Start** debug session
4. **Hard refresh** browser (Ctrl+Shift+R or Cmd+Shift+R)
5. **Navigate** to `/form-title-width-test`
6. **Click** "Show Form 1 (200px)" button
7. **Click** "Show Form 2 (300px)" button
8. **Verify** Form 1 has 200px title widths
9. **Verify** Form 2 has 300px title widths
10. **Open** browser DevTools (F12)
11. **Inspect** `.pd-form-body` elements - verify `style="--title-width: XXpx;"`
12. **Inspect** `.title-box` elements - verify no inline `<style>` tags in parent
13. **Check** computed width of `.title-box` elements (should be 200px and 300px)
### Browser DevTools Verification
**In Elements tab:**
```html
<!-- Form 1 -->
<div class="pd-form-body" style="--title-width: 200px;">
<div class="title-box" ...>
<!-- Width should compute to 200px -->
</div>
</div>
<!-- Form 2 -->
<div class="pd-form-body" style="--title-width: 300px;">
<div class="title-box" ...>
<!-- Width should compute to 300px -->
</div>
</div>
In Computed tab:
- Select a
.title-boxelement from Form 1 - Verify
width: 200px - Select a
.title-boxelement from Form 2 - Verify
width: 300px
Test existing pages that use PDFormBody:
- PDForm demo page
- PDForm2 demo page
- PDForm3 demo page
- PDForm4 demo page
- PDForm5 demo page
- Any custom forms in consuming applications
The !important flags are necessary because:
- Bootstrap's
.input-group-texthas default styles that affect width - Flexbox properties (flex-grow, flex-shrink) can override explicit width
- Multiple CSS classes on the same element create specificity challenges
- Component library context - need to ensure consistent behavior across applications
| Alternative | Why Not Chosen |
|---|---|
Unique CSS class names per instance (e.g., .title-box-abc123) |
? Still pollutes DOM with multiple <style> tags? More verbose HTML ? Harder to debug |
Blazor CSS isolation (.razor.css) |
? Would also work ?? Chosen solution is simpler and more direct ?? Same underlying mechanism (scoped styles) |
Inline styles directly on .title-box |
? Would require more extensive changes ? Harder to maintain ? Less flexible |
CSS custom properties (CSS variables) support:
| Browser | Version | Release Date | Support |
|---|---|---|---|
| Chrome | 49+ | Mar 2016 | ? Full |
| Firefox | 31+ | Jul 2014 | ? Full |
| Safari | 9.1+ | Mar 2016 | ? Full |
| Edge | 15+ | Apr 2017 | ? Full |
| Opera | 36+ | Mar 2016 | ? Full |
| IE 11 | - | - | ? Not Supported |
Note: IE 11 is end-of-life and not a target browser for .NET 9 Blazor applications.
- Component Audit: Review other components for similar inline style injection patterns
- Coding Guidelines: Establish library-wide guideline against inline
<style>tag injection - Pattern Library: Document this CSS custom property pattern for future components
- Automated Testing: Consider adding automated tests for CSS conflicts
- Link to any reported issues about form title width conflicts
- Link to MagicSuite issues mentioning this problem
- Link to GitHub discussions about CSS scoping in Blazor
Search Terms:
- "PDFormBody TitleWidth"
- "form title width conflict"
- "multiple forms CSS"
- "title-box width"
- Changes are backward compatible (no breaking changes)
- CSS rule correctly uses CSS custom properties
-
GetTitleWidthStyle()method returns correct format - No inline
<style>tags in component template - Build succeeds without errors or warnings
- Test page demonstrates the fix working
- Documentation is clear and accurate
- Code follows project conventions
- XML documentation is present and accurate
- Is the CSS specificity approach acceptable (using
!important)? - Should we add unit tests for the
GetTitleWidthStyle()method? - Should we add a warning when
TitleWidthis negative? - Do we need additional documentation in the Wiki?
- Should we add a blog post about this fix?
Effort: 2-3 points (Small)
Breakdown:
- CSS changes: 0.5 points
- Component updates: 1 point
- Test page creation: 0.5 points
- Testing & verification: 0.5 points
- Documentation: 0.5 points
Complexity: Low
- Well-defined solution
- Low risk
- No breaking changes
- Minimal testing required
- Ensure all changes are committed and pushed
- Verify build succeeds on CI/CD pipeline
- Review CHANGELOG.md entry
- Deploy updated library to NuGet
- Update version numbers
- Tag release in Git
- Monitor for any reported issues
- Verify in consuming applications (MagicSuite)
- Update documentation website
- Important: Notify developers to do hard browser refresh (Ctrl+Shift+R)
If issues arise:
- Revert commit(s)
- Re-deploy previous version
- Document issue for future fix attempt
- Feature flag could be added if needed for gradual rollout
- Slack announcement in #dev-blazor channel
- Email to development team
- Update in team standup/sprint review
- Release notes in GitHub release
- Close related issues with fix reference
- Update README if significant change
?? PDFormBody TitleWidth Fix Released!
We've fixed a CSS conflict issue where multiple forms with different TitleWidth
values on the same page would interfere with each other.
? What's Fixed:
- Multiple forms with different title widths now work correctly
- Cleaner DOM (no inline style tags)
- Better performance
?? Action Required:
- None! This is a non-breaking change
- Hard refresh your browser after updating (Ctrl+Shift+R or Cmd+Shift+R)
?? More Info:
- Test page: /form-title-width-test
- Documentation: [link]
- GitHub issue: #[issue-number]
- ? N inline
<style>tags (where N = number of forms) - ? CSS conflicts (last form's width applies to all)
- ? Developer workarounds required (
!important,:global()) - ? Support tickets about unexpected behavior
- ? 0 inline
<style>tags - ? 0 CSS conflicts
- ? No workarounds needed
- ? Issue eliminated at source
DOM Pollution (3 forms on page):
Before: +3 <style> tags
After: +0 <style> tags (-100%)
CSS Specificity Wars:
Before: Required !important overrides in consuming apps
After: No overrides needed (-100% workarounds)
Developer Experience:
Before: Confusing behavior, requires workarounds
After: Works as expected out of the box
- Before: Multiple forms with same width (bug)
- After: Multiple forms with different widths (fixed)
- Browser DevTools showing CSS custom properties
- Test page demonstrating fix
- Provided in this document
- Additional examples in Wiki
- Original bug report
- MagicSuite issue reference
- Technical proposal document
- IDE: Visual Studio 2022
- Framework: .NET 9
- Language: C# 13.0
- Project Type: Blazor Component Library
- Repository: https://github.com/panoramicdata/PanoramicData.Blazor
- Branch: main
- Developer: John Odlin (@john-odlin)
- Projects Tested:
- PanoramicData.Blazor (library)
- PanoramicData.Blazor.Demo (Blazor Server demo)
- PanoramicData.Blazor.WebAssembly (WASM demo)
- Browsers Tested:
- Chrome/Edge (Chromium)
- Firefox
- Safari (if available)
- Name: John Odlin
- Date: 2025-01-15
- Signature: ? Implementation complete and tested
- Name: [To be assigned]
- Date: [TBD]
- Signature: [Pending review]
- Name: [To be assigned]
- Date: [TBD]
- Signature: [Pending testing]
End of Jira Ticket
Issue Key: [To be assigned by Jira]
Type: Bug
Priority: Medium
Status: Ready for Development
Assignee: John Odlin
Reporter: John Odlin
Created: 2025-01-15
Updated: 2025-01-15
Quick Summary: Fixed CSS conflicts in PDFormBody when multiple forms with different TitleWidth values are on the same page by migrating from inline <style> tags to CSS custom properties.
Fix: Use --title-width CSS custom property instead of inline styles.
Breaking Changes: None
Testing: /form-title-width-test page added
Browser Support: All modern browsers (Chrome 49+, Firefox 31+, Safari 9.1+, Edge 15+)