mirror of https://github.com/rjbasitali/tutorials
chap10
parent
1980088e59
commit
a82345c5f7
|
|
@ -0,0 +1,138 @@
|
|||
# Making Our Website Responsive
|
||||
|
||||
Responsive Design adapts to the device of the user who's visiting our website.
|
||||
|
||||
|
||||
## Understanding Hardware Pixels Vs Software Pixels
|
||||
|
||||
The browser don't understand the differnce between a desktop device and a mobile device. Modern mobile devices have hardware pixels identical to that of the desktop displays. We can change the hardware pixels on mobile devices to software or css pixels using the `viewport` meta tag. Which adjusts the pixels using a [pixel ratio](https://mydevice.io).
|
||||
|
||||
We can add the `viewport` `<meta>` tag as a first step to make our website responsive.
|
||||
|
||||
```html
|
||||
<meta name="viewport" content="width=device-width, initial=scale=1.0">
|
||||
```
|
||||
|
||||
|
||||
## Comparing The `viewport` Metatag (HTML) And Media Queries (CSS)
|
||||
|
||||
Let us see the difference between both, and also understand why we need both to make our website responsive.
|
||||
|
||||
| Viewport | Media Queries |
|
||||
| --- | --- |
|
||||
| Adjust site to device viewport | Change design depending on size |
|
||||
| No design changes | Design changes defined by us |
|
||||
|
||||
|
||||
## Understanding The `viewport` Metatag
|
||||
|
||||
We can define different properties in the `content` attribute of the `viewport` metatag.
|
||||
|
||||
```html
|
||||
<meta name="viewport" content="width=device-width, initial=scale=1.0, maximum-scale=2.0, minimum-scale=1.0">
|
||||
```
|
||||
|
||||
Which are mostly to control the behavior of zoom level or scaling, e.g. initial level of zoom, minimum or maximum level of zoom etc.
|
||||
|
||||
|
||||
## Designing Websites Mobile First
|
||||
|
||||
We usually start creating a website using the **mobile first** approach. Which simply means we develop our websites in a way that looks nice on mobile devices first. Because we live in a mobile time, and most users will be visiting our websites through mobile devices.
|
||||
|
||||
The opposite approach, which isn't recommended, would be **desktop first**.
|
||||
|
||||
## Adding Our First Media Queries
|
||||
|
||||
The way we add media queries is using the `@media` annotation followed by a condition in our css, the condition should evaluate to `true` for the media query to be applied.
|
||||
|
||||
```css
|
||||
@media (min-width: 40rem) {
|
||||
/* the body of media query inludes regular css code - e.g. we can define css selectors here to overwrite */
|
||||
#product-overview {
|
||||
height: 40vh;
|
||||
background-position: 50% 25%;
|
||||
}
|
||||
|
||||
#product-overview h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As a common practice, we keep our media queries at the end of our css files or code to keep it structured.
|
||||
|
||||
|
||||
## Things To Keep In Mind When Working With Media Queries
|
||||
|
||||
* Think of media queries as conditions, that if evaluates to `true`, the code inside the media query is applied.
|
||||
* As we are following the **mobile first** approach, the code outside of media queries will specify the look of our website on mobile devices.
|
||||
* We can have more than one media queries at the same time to specify different limits.
|
||||
* When using multiple media queries, order really matter so order them from smaller to bigger values, otherwise the media query defined after will overwrite changes.
|
||||
|
||||
|
||||
## Finding The Right Breaking Points
|
||||
|
||||
Once again we can use [mydevice.io](https://mydevice.io) and go to the Compare Devices section to find the right breaking point for our media queries.
|
||||
|
||||
|
||||
## Creating The Mobile First Design For Our Plans
|
||||
|
||||
We can go to our `.plan {}` class selector and remove the `display: inline-block;` property to make it a block level element, because we are following the **mobile first** appraoch, so making all the elements work for a mobile display first.
|
||||
|
||||
|
||||
## Making The Plans Responsive
|
||||
|
||||
Following media query is applied for desktop version of the website, because we are following a **mobile first** approach, we are only using media queries for desktop design:
|
||||
|
||||
```css
|
||||
@media (min-width: 40rem) {
|
||||
.plan__list {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.plan {
|
||||
display: inline-block;
|
||||
width: 30%;
|
||||
vertical-align: middle;
|
||||
min-width: 13rem;
|
||||
max-width: 25rem;
|
||||
}
|
||||
|
||||
.plan--highlighted {
|
||||
box-shadow: 2px 2px 2px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Working With Logical Operators
|
||||
|
||||
We can use the logical operators between multiple conditions in our media queries, e.g. the following media query will be applied if both of the conditions are `true`:
|
||||
|
||||
```css
|
||||
@media (min-width: 40rem) and (min-height: 60rem) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
```css
|
||||
@media (min-width: 40rem), (orientation: portrait) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Note that we can also use `,` comma separated list of conditions, instead of the `and` operator.
|
||||
|
||||
|
||||
## Positioning Our Footer Correctly
|
||||
|
||||
```css
|
||||
main {
|
||||
min-height: calc(100vh - 3.5rem - 8rem);
|
||||
}
|
||||
```
|
||||
|
||||
Here, `3.5rem` is the height of the top navigation bar, and `8rem` is the height of the footer.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# Adding And Styling Forms
|
||||
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
# Working With JavaScript And CSS
|
||||
|
||||
## Adding A Modal
|
||||
|
||||
CSS for the modal:
|
||||
|
||||
```css
|
||||
.modal {
|
||||
position: fixed;
|
||||
display: none;
|
||||
z-index: 200;
|
||||
top: 20%;
|
||||
left: 30%;
|
||||
width: 40%;
|
||||
background: white;
|
||||
padding: 1rem;
|
||||
border: 1px solid #ccc;
|
||||
box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.modal__title {
|
||||
text-align: center;
|
||||
margin: 0 0 1rem 0;
|
||||
}
|
||||
|
||||
.modal__actions {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.modal__action {
|
||||
border: 1px solid #0e4f1f;
|
||||
background: #0e4f1f;
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
font: inherit;
|
||||
padding: 0.5rem 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.modal__action:hover,
|
||||
.modal__action:active {
|
||||
background: #2ddf5c;
|
||||
border-color: #2ddf5c;
|
||||
}
|
||||
|
||||
.modal__action--negative {
|
||||
background: red;
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
.modal__action--negative:hover,
|
||||
.modal__action--negative:active {
|
||||
background: #ff5454;
|
||||
border-color: #ff5454;
|
||||
}
|
||||
```
|
||||
|
||||
## Selecting & Manipulating Styles With JavaScript
|
||||
|
||||
JavaScript allows us to run code after the page is loaded. We can use it to change the content or styling of the page.
|
||||
|
||||
We can add the JavaScript using the inline `<script src="shared.js"></script>` element, preferebly at the end of the document, before the close `</body>` tag, so we are sure everything else is loaded.
|
||||
|
||||
```html
|
||||
...
|
||||
<script src="shared.js"></script>
|
||||
</body>
|
||||
```
|
||||
|
||||
Inside JavaScript, we can use the `querySelector('')` to select an element. The `querySelector('')` only selects a single element, that is the first element it finds.
|
||||
|
||||
```js
|
||||
var backdrop = document.querySelector('.backdrop');
|
||||
console.dir(backdrop);
|
||||
```
|
||||
|
||||
You can use any valid CSS selector name as an argument to the `querySelector('')`.
|
||||
|
||||
To select all elements or array of elements, we can use the `querySelectorAll('')` method.
|
||||
|
||||
The `style` property of an html node in JavaScript only shows the inline styles. We can use this property to manipulate the inline styles of an element, keep in mind that inline styles has the highest specificity and overwrites any other styles applied.
|
||||
|
||||
|
||||
## Adding An Event Listener
|
||||
|
||||
```js
|
||||
var backdrop = document.querySelector('.backdrop');
|
||||
var modal = document.querySelector('.modal');
|
||||
var selectPlanButtons = document.querySelectorAll('.plan button');
|
||||
|
||||
for (var i = 0; i < selectPlanButtons.length; i++>) {
|
||||
selectPlanButtons[i].addEventListener('click', function() {
|
||||
modal.style.display = 'block';
|
||||
backdrop.style.display = 'block';
|
||||
})
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Adding A Side Navigation
|
||||
|
||||
Add a side navigation bar for mobile devices:
|
||||
|
||||
```html
|
||||
<nav class="mobile-nav">
|
||||
<ul class="mobile-nav__items">
|
||||
<li class="mobile-nav__item">
|
||||
<a href="packages/index.html">Packages</a>
|
||||
</li>
|
||||
<li class="mobile-nav__item">
|
||||
<a href="customers/index.html">Customers</a>
|
||||
</li>
|
||||
<li class="mobile-nav__item mobile-nav__item--cta">
|
||||
<a href="start-hosting/index.html">Start Hosting</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
```
|
||||
|
||||
```css
|
||||
.mobile-nav {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 101;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: white;
|
||||
width: 80%;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.mobile-nav__items {
|
||||
width: 90%;
|
||||
height: 100%;
|
||||
list-style: none;
|
||||
margin: 10% auto;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mobile-nav__item {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
.mobile-nav__item a {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Opening And Closing The Hamburger Menu
|
||||
|
||||
```js
|
||||
var backdrop = document.querySelector(".backdrop");
|
||||
var modal = document.querySelector(".modal");
|
||||
var modalNoButton = document.querySelector(".modal__action--negative");
|
||||
var selectPlanButtons = document.querySelectorAll(".plan button");
|
||||
var toggleButton = document.querySelector('.toggle-button');
|
||||
var mobileNav = document.querySelector('.mobile-nav');
|
||||
|
||||
// console.dir(backdrop);
|
||||
for (var i = 0; i < selectPlanButtons.length; i++) {
|
||||
selectPlanButtons[i].addEventListener("click", function() {
|
||||
modal.style.display = "block";
|
||||
backdrop.style.display = "block";
|
||||
});
|
||||
}
|
||||
|
||||
backdrop.addEventListener("click", function() {
|
||||
mobileNav.style.display = 'none';
|
||||
closeModal();
|
||||
});
|
||||
|
||||
modalNoButton.addEventListener("click", closeModal);
|
||||
|
||||
function closeModal() {
|
||||
backdrop.style.display = "none";
|
||||
modal.style.display = "none";
|
||||
}
|
||||
|
||||
toggleButton.addEventListener('click', function() {
|
||||
mobileNav.style.display = 'block';
|
||||
backdrop.style.display = 'block';
|
||||
});
|
||||
```
|
||||
|
||||
## Manipulating Element Classes
|
||||
|
||||
Instead of setting inline styles using the `style` property on html node objects, we can also add or remove css classes to a html node using the `classList` property.
|
||||
|
||||
```css
|
||||
.open {
|
||||
display: block !important;
|
||||
}
|
||||
```
|
||||
|
||||
```js
|
||||
// to display the modal
|
||||
modal.classList.add('open');
|
||||
backdrop.classList.add('open');
|
||||
|
||||
// to hide the modal
|
||||
modal.classList.remove('open');
|
||||
backdrop.classList.remove('open');
|
||||
```
|
||||
|
||||
|
||||
## Understanding Property Notations
|
||||
|
||||
When using css properties using JavaScript, we use camelCase notation instead of kebab-case. e.g. `modal.style.backgroundImage`.
|
||||
Loading…
Reference in New Issue