Reputation: 1219
I'm trying to reproduce the layout below in Vaadin 14.
The content area should fill the available space. How can I have scrollbars on just the content area, if the content is too large?
With the code below, scrollbars are added to both the main page and the content area.
As a workaround, I can get it to work by giving the VerticalLayout returned by getContent() a fixed size, but in practice the content size won't be known.
@Route
public class LayoutTest extends VerticalLayout {
public LayoutTest() {
setPadding(false);
setSpacing(false);
setSizeFull();
setDefaultHorizontalComponentAlignment(Alignment.STRETCH);
Div header = new Div(new H2("Title"));
header.setHeight("4em");
header.getStyle().set("flex-shrink", "0");
Div leftMenu = createLeftMenu();
VerticalLayout content = createContentArea();
HorizontalLayout layout = new HorizontalLayout(leftMenu, content);
layout.setPadding(false);
layout.setSpacing(false);
layout.setHeight("100px");
layout.expand(content);
expand(layout);
add(header);
add(layout);
}
private HorizontalLayout createTopMenu() {
HorizontalLayout menu = new HorizontalLayout(new Button("Menu 1"), new Button("Menu 2"), new Button("Menu 3"));
menu.setPadding(false);
menu.getStyle().set("background", "#fafafa");
return menu;
}
private Div createLeftMenu() {
Div navigation = new Div();
navigation.setText("Left menu");
navigation.setWidth("20em");
navigation.getStyle().set("background", "#fafafa");
navigation.getStyle().set("flex-shrink", "0");
return navigation;
}
private VerticalLayout createContentArea() {
VerticalLayout layout = new VerticalLayout();
layout.setDefaultHorizontalComponentAlignment(Alignment.STRETCH);
layout.setPadding(false);
layout.add(createTopMenu());
H3 subtitle = new H3("Content");
subtitle.getStyle().set("flex-shrink", "0");
layout.add(subtitle);
VerticalLayout content = createContent();
// Giving the content a fixed size works, but is not desired
// content.setHeight("10000px");
// content.setWidth("1000px");
Div scroller = new Div(content);
scroller.getStyle().set("overflow", "auto");
scroller.getStyle().set("border-style", "solid");
layout.add(scroller);
HorizontalLayout buttons = new HorizontalLayout(new Button("Button 1"), new Button("Button 2"), new Button("Button 3"));
buttons.getStyle().set("flex-shrink", "0");
layout.add(buttons);
layout.expand(scroller);
return layout;
}
private VerticalLayout createContent() {
VerticalLayout content = new VerticalLayout();
for (int i = 0; i < 100; ++i) {
Div div = new Div(new Span("data" + i));
div.setWidth("2000px");
div.setHeight("20px");
div.getStyle().set("background", "#cccccc");
content.add(div);
}
return content;
}
}
Upvotes: 1
Views: 559
Reputation: 1219
I found a solution by adapting this answer to Make a div fill the height of the remaining screen space
It uses divs with display:table, display:table-row and display:table-cell.
The relevant change is to the createContentArea() method. I would be interested to know if there is a higher-level solution.
This works on Firefox, Chrome and Edge.
@Route
public class LayoutTest2 extends VerticalLayout {
public LayoutTest2() {
setPadding(false);
setSpacing(false);
setSizeFull();
setDefaultHorizontalComponentAlignment(Alignment.STRETCH);
Div header = new Div(new H2("Title"));
header.setHeight("4em");
header.getStyle().set("flex-shrink", "0");
Div leftMenu = createLeftMenu();
Div content = createContentArea();
HorizontalLayout layout = new HorizontalLayout(leftMenu, content);
layout.setPadding(false);
layout.setSpacing(false);
layout.setHeight("100px");
layout.expand(content);
expand(layout);
add(header);
add(layout);
}
private HorizontalLayout createTopMenu() {
HorizontalLayout menu = new HorizontalLayout(new Button("Menu 1"), new Button("Menu 2"), new Button("Menu 3"));
menu.setPadding(false);
menu.getStyle().set("background", "#fafafa");
return menu;
}
private Div createLeftMenu() {
Div navigation = new Div();
navigation.setText("Left menu");
navigation.setWidth("20em");
navigation.getStyle().set("background", "#fafafa");
navigation.getStyle().set("flex-shrink", "0");
return navigation;
}
private Div createContentArea() {
Div table = new Div();
table.getStyle().set("display", "table")
.set("width", "100%")
.set("height", "100%");
Div topMenu = new Div(createTopMenu());
topMenu.getStyle().set("display", "table-row");
table.add(topMenu);
Div subtitle = new Div(new H3("Content"));
subtitle.getStyle().set("display", "table-row");
table.add(subtitle);
Div tableRowBody = new Div();
tableRowBody.getStyle().set("display", "table-row")
.set("height", "100%");
Div outerWrapper = new Div();
outerWrapper.getStyle().set("display", "table-cell")
.set("height", "100%");
tableRowBody.add(outerWrapper);
Div innerWrapper = new Div();
innerWrapper.getStyle().set("height", "100%")
.set("position", "relative")
.set("overflow", "auto")
.set("border", "solid");
outerWrapper.add(innerWrapper);
Div bodyContent = new Div(createContent());
bodyContent.getStyle().set("position", "absolute")
.set("top", "0")
.set("bottom", "0")
.set("left", "0")
.set("right", "0");
innerWrapper.add(bodyContent);
table.add(tableRowBody);
HorizontalLayout buttons = new HorizontalLayout(new Button("Button 1"), new Button("Button 2"), new Button("Button 3"));
table.add(buttons);
return table;
}
private VerticalLayout createContent() {
VerticalLayout content = new VerticalLayout();
for (int i = 0; i < 100; ++i) {
Div div = new Div(new Span("data" + i));
div.setWidth("2000px");
div.setHeight("20px");
div.getStyle().set("background", "#cccccc");
content.add(div);
}
return content;
}
}
Upvotes: 1