summaryrefslogtreecommitdiffstats
path: root/documentation/themes/themes-responsive.asciidoc
blob: 07c0f47ce6ef929d7e5a6eac7db89ce1b53249cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
---
title: Responsive Themes
order: 10
layout: page
---

[[themes.responsive]]
= Responsive Themes

((("[classname]#responsive# extension", id="term.themes.responsive", range="startofrange")))


((("CSS selections")))
((("extension")))
Vaadin includes support for responsive design which enables size range
conditions in CSS selectors, allowing conditional CSS rules that respond to size
changes in the browser window on the client-side.

ifdef::web[]
See the link:https://vaadin.com/blog/-/blogs/3126636[Vaadin Blog article on
Responsive design] for some additional
information.
endif::web[]

You can use the [classname]#Responsive# extension to extend either a component,
typically a layout, or the entire UI. You specify the component by the static
[methodname]#makeResponsive()# method.


----
// Have some component with an appropriate style name
VerticalLayout l = new VerticalLayout();

Label c = new Label("Here be text");
l.addStyleName("myresponsive");
l.addComponent(c);
        
// Enable Responsive CSS selectors for the component
Responsive.makeResponsive(l);
----

You can now use [literal]#++width-range++# and [literal]#++height-range++#
conditions in CSS selectors as follows:


----
/* Basic settings for all sizes */
.myresponsive {
    padding: 5px;
    line-height: 36pt;
}
    
/* Small size */
.myresponsive[width-range~="0-300px"] {
    background: orange;
    font-size: 16pt;
}

/* Medium size */
.myresponsive[width-range~="301px-600px"] {
    background: azure;
    font-size: 24pt;
}

/* Anything bigger */
.myresponsive[width-range~="601px-"] {
    background: palegreen;
    font-size: 36pt;
}
----

You can have overlapping size ranges, in which case all the selectors matching
the current size are enabled.

ifdef::web[]
Note that responsive themes currently
link:https://dev.vaadin.com/ticket/16249[do not work together with] stylesheets
or widget sets loaded from a different domain than the Vaadin application. Such
resources must be loaded from the same domain as the application. The problem
occurs only in Firefox. A SecurityError is shown in the debug window. The
limitation concerns stylesheets such as for web fonts served from external
sites, as described in
<<themes-fonts#themes.fonts.webfonts,"Loading
Web Fonts">>.
endif::web[]

ifdef::web[]
[[themes.responsive.wrap]]
== Flexible Wrapping

You can use the [classname]#CssLayout# to have automatic wrap-around when the
components in the layout would go off right side of the layout. Components that
wrap must, however, have either undefined or fixed width, and thereby can not
utilize the full area of the screen. With the [classname]#Responsive# extension,
you can have more flexible wrap-around that gives the component tiles maximum
width.

In the following, we have a text and image box, which are laid out horizontally
with 50-50 sizing if the screen is wide enough, but wrap to a vertical layout if
the screen is narrow.


----
CssLayout layout = new CssLayout();
layout.setWidth("100%");
layout.addStyleName("flexwrap");
content.addComponent(layout);
        
// Enable Responsive CSS selectors for the layout
Responsive.makeResponsive(layout);

Label title = new Label("Space is big, really big");
title.addStyleName("title");
layout.addComponent(title);

Label description = new Label("This is a " +
    "long description of the image shown " +
    "on the right or below, depending on the " +
    "screen width. The text here could continue long.");
description.addStyleName("itembox");
description.setSizeUndefined();
layout.addComponent(description);
        
Image image = new Image(null,
        new ThemeResource("img/planets/Earth.jpg"));
image.addStyleName("itembox");
layout.addComponent(image);
----

The SCSS could be as follows:


----
/* Various general settings */
.flexwrap {
    background: black;
    color: white;

    .title {
        font-weight: bold;
        font-size: 20px;
        line-height: 30px;
        padding: 5px;
    }
    
    .itembox {
        white-space: normal;
        vertical-align: top;
    }
    
    .itembox.v-label {padding: 5px}
}
    
.flexwrap[width-range~="0-499px"] {
    .itembox {width: 100%}
}
    
.flexwrap[width-range~="500px-"] {
    .itembox {width: 50%}
}
----

The layout in the wide mode is shown in <<figure.theme.responsive.flexwrap>>.

[[figure.theme.responsive.flexwrap]]
.Flexible Wrapping
image::img/addon-responsive-flexwrap.png[]

You could also play with the [literal]#++display: block++# vs
[literal]#++display: inline-block++# properties.

Notice that, while the [classname]#Responsive# extension makes it possible to do
various CSS trickery with component sizes, the normal rules for component and
layout sizes apply, as described in
<<layout-settings#layout.settings.size,"Layout
Size">> and elsewhere, and you should always check the size behaviour of the
components. In the above example, we set the label to have undefined width,
which disables word wrap, so we had to re-enable it.

endif::web[]

ifdef::web[]
[[themes.responsive.display]]
== Toggling the Display Property

((("display (CSS
property)")))
The [literal]#++display++# property allows especially powerful ways to offer
radically different UIs for different screen sizes by enabling and disabling UI
elements as needed. For example, you could disable some parts of the UI when the
space gets too small, but bring forth navigation buttons that, when clicked, add
component styles to switch to the hidden parts.

In the following, we simply show alternative components based on screen width:


----
CssLayout layout = new CssLayout();
layout.setWidth("100%");
layout.addStyleName("toggledisplay");
content.addComponent(layout);
        
// Enable Responsive CSS selectors for the layout
Responsive.makeResponsive(layout);

Label enoughspace =
    new Label("This space is big, mindbogglingly big");
enoughspace.addStyleName("enoughspace");
layout.addComponent(enoughspace);
        
Label notenoughspace = new Label("Quite small space");
notenoughspace.addStyleName("notenoughspace");
layout.addComponent(notenoughspace);
----

The SCSS could be as follows:


----
/* Common settings */
.toggledisplay {
    .enoughspace, .notenoughspace {
        color: white;
        padding: 5px;
    }
    
    .notenoughspace { /* Really small */
        background: red;
        font-weight: normal;
        font-size: 10px;
        line-height: 15px;
    }

    .enoughspace { /* Really big */
        background: darkgreen;
        font-weight: bold;
        font-size: 20px;
        line-height: 30px;
    }
}
    
/* Quite little space */
.toggledisplay[width-range~="0-499px"] {
    .enoughspace    {display: none}
}
    
/* Plenty of space */
.toggledisplay[width-range~="500px-"] {
    .notenoughspace {display: none}
}
----

endif::web[]

ifdef::web[]
[[themes.responsive.demos]]
== Responsive Demos

You can find a simple responsive demo at
link:http://demo.vaadin.com/responsive/[demo.vaadin.com/responsive]. It
demonstrates the flexible wrapping technique described in
<<themes.responsive.wrap>>.

((("Parking
demo")))
((("TouchKit", "Parking
demo")))
link:https://demo.vaadin.com/parking/[The Parking demo for TouchKit] uses a responsive theme to adapt to mobile
devices with different screen sizes and when the screen orientation changes.

endif::web[]

(((range="endofrange", startref="term.themes.responsive")))