I am trying to learn some React and CSS and I am struggling with one thing.
I am trying to create a chat page , but when there are many messages , the message - container pushes down the input box.
React code:
const message = useRef()
function submit(e) {
e.preventDefault();
addMessage(msgBox => [...msgBox , message.current.value])
}
const [msgBox, addMessage] = useState(["John: Hi"])
return (
<>
<div className = "chat-container">
{msgBox.map((msg) => {
return <div><span>{msg}</span><br/></div>
})}
</div>
<div className = "message-box">
<Form onSubmit = {submit}>
<input ref = {message} />
<Button type = "submit" className = "mb-1 position-fixed">
Send
</Button>
</Form>
</div>
</>
)
CSS :
* {
margin: 0;
padding: 0;
}
.chat-container {
min-height: 90vh;
min-width: 80%;
position: relative;
}
span {
padding: 60px;
}
.message-box {
min-height: 10vh;
position: absolute;
}
.message-box > form > input {
margin-left: 60px;
}
I tried to play around with the position properties, but I coudn't make it happen.I want the message-box to not be pushed down by chat-container when there are too many messages.
I want when there are too many messages the chat-container not to overlap at all the message-box and be able to scroll there.
Any help?
Set max-height on .chat-container. You can use another value instead of 500px. Play with it to find a value that matches your design.
.chat-container {
max-height: 500px
overflow: scroll
}
Update
If the height of the .chat-container changes and you want to push the input at the bottom, do this:
Give all the parent of the .chat-container including html and body height: 100%.
Put the .chat-container and form in a html element that is flex and its flex-direction is column.
Use flex-grow: 1 on the .chat-container so that it always takes all the available space.
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.chat-container {
flex-grow: 1;
overflow: scroll;
}
<div class="container">
<div class="chat-container">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus expedita reiciendis, magnam provident fugit ad odit, nulla a nisi repellat eaque minus assumenda neque ea cumque blanditiis nobis repudiandae? Aliquid.</p>
</div>
<div class="message-box">
<Form onSubmit={ submit}>
<input ref={ message} />
<Button type="submit" class="mb-1 position-fixed">
Send
</Button>
</Form>
</div>
</div>
You can adjust the height of the form.
I just want to add a bit more to the solution, as the previous answers are quite poor, since whenever the viewport changes, the 500px value would not work. In this app case, we have:
The container with the chat messages, which should be scrollable and should have a fixed height.
The container with the input which would have the rest of the height.
I suppose you are designing an app like WhatsApp Web, so you would have something like the following:
Here is how the structure would look in HTML:
<div class="chat-wrapper">
<div class="chat-messages">
<div class="message left">Some text</div>
<div class="message left">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In nulla sem, placerat a est eu, interdum consectetur ipsum. Sed sed libero ac mauris scelerisque convallis et eget elit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris vel iaculis purus. Nunc placerat nisi sapien, id facilisis sapien faucibus sit amet. Vestibulum felis eros, fermentum quis augue eu, vehicula dapibus nisi. Suspendisse potenti.</div>
<div class="message right">Some text</div>
<div class="message right">Some text</div>
<div class="message left">Some text</div>
<div class="message right">Lorem ipsum dolor sit amet, consectetur adipiscing elit. In nulla sem, placerat a est eu, interdum consectetur ipsum. Sed sed libero ac mauris scelerisque convallis et eget elit. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Mauris vel iaculis purus. Nunc placerat nisi sapien, id facilisis sapien faucibus sit amet. Vestibulum felis eros, fermentum quis augue eu, vehicula dapibus nisi. Suspendisse potenti.</div>
<div class="message left">Some text</div>
<div class="message right">Some text</div>
<div class="message right">Some text</div>
<div class="message left">Some text</div>
</div>
<div class="chat-input">
<input name="message" class="chat-input" />
</div>
</div>
Now, the window height would be the 100% of the height, which is the same as 100vh. From here, you can create a parent container, whose height would be the entire viewport:
.chat-wrapper {
height: 100vh;
width: 50%;
margin: auto;
}
The chat wrapper would be the class for the parent of the div containers of the messages. Then, we would define two more classes, that will be the containers for the div's of the messages and the input itself:
/* Container for the message */
.chat-messages {
padding: 16px 36px 0;
min-height: calc(100% - 75px);
max-height: calc(100% - 75px);
overflow: auto;
}
/* Container for the input */
.chat-input {
background-color: #efefef;
min-height: 75px;
max-height: 75px;
display: flex;
justify-content: flex-left;
align-items: center;
padding: 0 32px;
}
The trick here, is how we calculate the height of the messages. As you can see, we are using the 100% of the height, but we are also subtracting the fixed height of the input container. Therefore, the messages container will always push the input container to the bottom, without removing it from the actual viewport. Plus, we add the overflow: auto prop, which will allow the scrolling inside the container.
Finally, we can add other styling classes to the other fields.
/* Default styling for the messages */
.message {
padding: 8px;
border-radius: 8px;
width: fit-content;
max-width: 65%;
margin-bottom: 8px;
border: 1px solid #dedede;
}
/* Default styling for the right messages */
/* You could also modify the styled for the left messages with the left class */
.message.right {
background-color: #dcf8c6;
margin-left: auto;
}
.chat-input {
padding: 8px;
width: 100%;
height: 65%;
border-radius: 8px;
outline: none;
border: none;
}
Related
I have two sibling elements which each contain dynamic content.
<div class="flex">
<div class="sibling-1"></div>
<div class="sibling-2"></div>
</div>
In some cases sibling-1 will have more content then sibling-2 and vice versa.
I would like the height of the second element sibling-2 always equal the height of the first sibling-1. If the height of sibling-2 is greater then the height of sibling-1 it will overflow the flex div and thus be scrollable.
Is there any way to accomplish this with Flexbox?
Yes, it is possible. Leave the sibling setting the max height alone and set the others' flex-basis: 0 and flex-grow: 1, which according to the spec will expand them to their sibling's height. No absolute positioning. No setting height on any elements.
main {
display: flex;
}
section {
display: flex;
flex-direction: column;
width: 7em;
border: thin solid black;
margin: 1em;
}
:not(.limiter)>div {
flex-basis: 0px;
flex-grow: 1;
overflow-y: auto;
}
<main>
<section>
<div>I'm longer and will scroll my overflow. in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text
in flow text in flow text in flow text in flow text in flow text in flow text in</div>
</section>
<section class="limiter">
<div>Every parent's siblings match my height. in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text</div>
</section>
<section>
<div>I'm shorter but still match the height. in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text in flow text</div>
</section>
</main>
Is there any way to accomplish this with Flexbox?
Basically, no. The flex equal heights feature is based on the height of the container, not any particular sibling.
So sibling-1 and sibling-2 can always be equal height.
But flexbox has no built-in mechanism to limit the height of items to the height of one sibling.
Consider JavaScript or CSS positioning properties.
Here's an example using absolute positioning:
.flex {
display: flex;
width: 200px;
position: relative;
}
.flex>div {
flex: 0 0 50%;
border: 1px solid black;
box-sizing: border-box;
}
.sibling-2 {
position: absolute;
left: 50%;
top: 0;
bottom: 0;
right: 0;
overflow: auto;
}
<div class="flex">
<div class="sibling-1">text<br>text<br>text<br>text<br>text<br>text<br></div>
<div class="sibling-2">text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br>text<br></div>
</div>
jsFiddle
Yes you can accomplish this by making siblings 1 and 2 also flex containers, then on sibling-2 make an absolute div (also flex container) inside that will be the parent of your scroller
<div class="sibling-1 flex sibling"></div>
<div class="sibling-2 flex sibling">
<div class="absolute flex scroller-wrap">
<div class="relative vertical-scroller">
your content here
</div>
</div>
</div>
css:
.relative{
position:relative;
}
.absolute{
position:absolute;
}
.flex{
display:flex;
}
.sibling-2{
flex:1;
}
.scroller-wrap{
height:100%;
}
on sibling 2 just set a minimum height on pixels - useful on responsive cases if siblings 1 and 2 stack each other on mobile
As I mentioned in the comments and has been continued in other answers, there is no flexbox method.
It is possible using position:absolute on the second sibling though...but since that's not actually a flexbox solution, this is here for information only.
.flex {
margin: 1rem auto;
position: relative;
display: flex;
}
.sibling-1 {
flex: 0 0 50%;
}
.sibling-2 {
position: absolute;
right: 0;
width: 50%;
height: 100%;
overflow: auto;
}
* {
margin: 0;
outline: 0;
}
.flex {
width: 80%;
margin: 1rem auto;
border: 1px solid grey;
position: relative;
display: flex;
}
.sibling-1 {
flex: 0 0 50%;
}
.sibling-2 {
position: absolute;
right: 0;
width: 50%;
height: 100%;
overflow: auto;
}
<div class="flex">
<div class="sibling-1">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Labore quia, voluptatum! Perspiciatis praesentium nemo, labore mollitia numquam recusandae voluptatem consectetur amet deleniti cum nesciunt blanditiis, esse quis doloremque vero! Reiciendis
porro impedit perspiciatis. Amet in praesentium molestias ipsum ad quis quia doloribus, veniam unde, ea ducimus rerum porro tenetur voluptatem, a laudantium. Accusantium provident voluptatibus perferendis hic blanditiis laborum amet consequatur
esse, fugiat doloremque consectetur ullam sequi, ratione perspiciatis, voluptatem eaque vitae rem repellendus in architecto vel nulla animi neque. Accusantium animi voluptatum, suscipit possimus,</p>
</div>
<div class="sibling-2">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eaque modi quibusdam aliquam officia illo itaque ratione, iste architecto ad blanditiis fugiat sequi laborum cupiditate voluptatum, autem non? Quibusdam ad eius hic rem id. Libero, tempora
dicta reiciendis placeat nihil quia fuga iste aliquid quo minus labore sapiente fugit, similique non aliquam, beatae pariatur nobis fugiat! Ipsam nobis fugit maxime aliquam accusamus explicabo nostrum ab nemo adipisci dolorem qui porro ea pariatur
corporis aut reiciendis optio, sint eum nam suscipit itaque aspernatur recusandae. Cumque qui quod doloremque. Ut voluptates, asperiores, laborum excepturi quam odit, quos rerum assumenda sapiente saepe nisi? Numquam placeat repellat eum dolorem
reprehenderit dolores culpa id explicabo consequuntur. Quas nobis veritatis tempora animi similique earum commodi, laborum blanditiis dolor illo, eaque accusamus aliquid nam a ex, velit, maiores natus. Id totam ullam corporis. Repellat aperiam,
distinctio maxime, dolorum illum labore recusandae. Sequi repellendus provident deserunt amet culpa, ratione dignissimos! Quibusdam delectus mollitia, ducimus. Error id architecto, ea molestias voluptate impedit inventore amet ducimus modi repellat
in. Asperiores soluta veritatis id eius, distinctio nisi voluptates voluptatibus iste iusto error officia tempore! Ducimus sed commodi quisquam provident iure voluptatum aliquam, nobis rem dolore, consectetur, dolor rerum eum nam adipisci, libero
beatae eaque aliquid sapiente? Eius, earum quas nostrum quasi reiciendis officia quaerat omnis. Cupiditate suscipit et tempora quibusdam perspiciatis eius cum, nisi facere animi. Delectus magnam inventore ipsum, veritatis reiciendis. Ipsum adipisci
recusandae, similique quas labore voluptas animi eaque velit, alias eveniet qui libero obcaecati suscipit, quam nihil quos placeat.</p>
</div>
</div>
From your code and to avoid extra wrapping , sticky on a side, height:0 on the other then overflow:auto on the parent can also do the job with flex:
example (you will easily understand it)
.flex {
display: flex;
/* demo purpose */
width: 500px;
border: solid;
overflow: auto;/* make the parent scroll */
gap:0.5em;
}
.flex .sibling-1 {
position: sticky;/* stick the reference for the height */
top: 0;
}
.flex .sibling-2 {
height: 0;/* give it no height to start from and let the parent show the scrollbar */
}
<div class="flex">
<div class="sibling-1">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus
lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor,
facilisis luctus, metus</p>
</div>
<div class="sibling-2">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus
lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor,
facilisis luctus, metus</p>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est.
Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus
lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan porttitor,
facilisis luctus, metus</p>
</div>
</div>
My simplified (to me at least) code snippet based on Lucent's answer:
main {
display: flex;
font-family: "nunito"
}
section1 {
display: flex;
flex-direction: column;
width: 15rem;
border: thin solid gray;
}
section2 {
display: flex;
flex-direction: column;
width: 15rem;
border: thin solid gray;
}
section1 > div {
flex-basis: 0px;
flex-grow: 1;
overflow-y: auto;
}
<main>
<section1 class="scroll">
<div>I'm a div in section 1 ---
I have extra css rules of flex-basis 0px (making me as small as possible), flex 1 (making me fill up available space), and overflow y auto (making me scroll the extra content) --- My parent section 1 is a flex column --- My grandparent main is a flex row ---</div>
</section1>
<section2>
<div>I'm a div in section 2. --- My parent section 2 is a flex column --- My grandparent main is a flex row --- The height of the div in section 1 will adjust to my height.</div>
</section2>
</main>
I have a two-column layout. The main text on the left, and a sidebar on the right (float: right; width: 30%).
On small browsers, I'd like to first show the main text, and then the sidebar. But if I remove the float from the sidebar with a media query, it shows up first.
I don't want to make the main text another float, because I want it to wrap around the sidebar if the text is long and the sidebar short.
I'm looking for something that's not Javascript if possible.
CSS order Property
When in mobile screen size:
Make the containing tag a flex-container (column wise)
Remove the float related properties from sidebar
Apply order property to the content tag (element with text) and sidebar
The number value of the order property belonging to content tag should be less than the order value of sidebar.
The following demo features:
600px+ Width
Container - <article>
Sidebar - <aside>
float: right
clearfix hack - article::after {...}
Content - <p class="content">
600px Max Width (Mobile)
Container - <article>
flex-container (column)
Sidebar - <aside>
float: none
clearfix hack - removed
order: 3
Content - <p class="content">
order: 2
Demo
Note: View demo in full page mode not in the initial iframe. Resize the window to see the media query work.
:root {
font: 400 3vw/6vh Arial
}
html,
body {
width: 100%;
height: 100%;
padding: 1vh 1vw;
}
main {
width: 90vw;
height: auto;
margin: 5vh -6vw 10vh -6vw;
padding: 3vh 15vw 5vh 5vw;
}
section {
width: 100%;
height: 100%;
}
/*
Begin Sidebar Rulesets
*/
aside {
float: right;
width: 30%;
height: 50%;
border: 3px ridge grey;
margin-left: 3vw;
padding: 5vh 1vw 5vh 2vw;
}
/*
Clearfix hack
*/
aside::after {
content: "";
clear: both;
display: table;
}
/*
End Sidebar Rulesets
*/
header,
footer {
padding: 2vh 0 2vh 0;
margin: 2vh 0;
line-height: 8vh;
}
header {
border-bottom: 5px ridge grey;
}
footer {
border-top: 5px ridge grey
}
h1 {
font-size: 1.75rem;
letter-spacing: 1vw;
margin: 0 0 3vh;
}
h2 {
font-size: 1.45rem;
letter-spacing: 0.75vw;
margin: 0 0 3vh;
}
h3 {
font-size: 1.2rem;
letter-spacing: 0.5vw;
margin: 0 0 3vh;
}
address {
float: right;
font-size: 0.85rem;
margin: 2vh 1vw 5vh 3vw
}
ul {
list-style: none;
padding-left: 1vw
}
li {
margin-bottom: 2vh
}
.content {
font-size: 0.9rem;
line-height: 7vh;
}
/*
Begin Mobile Media Queries
*/
/*
Remove float properties from sidebar (aside)
Convert container (article) into a flex container
Use order property to rearrange how the flex-items appear
(header, p.content, aside)
*/
#media screen and (max-width: 600px) {
article {
display: flex;
flex-flow: column nowrap;
justify-content: center;
align-items: center;
}
article>header {
order: 1;
}
.content {
order: 2;
}
aside {
float: none;
width: 100%;
order: 3
}
aside::after {
content: none;
}
}
/*
End Mobile Media Queries
*/
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<!-- <link> tags go here -->
<style>
/* CSS Rulesets go here */
</style>
</head>
<body>
<main>
<section>
<header>
<h1>Main Title</h1>
</header>
<!-- Begin Container -->
<article>
<header>
<h2>Topic Title</h2>
</header>
<!-- Begin Sidebar -->
<aside>
<nav>
<header>
<h3>Sidebar Title</h3>
</header>
<hr>
<ul>
<li>
<a href='#/'>Link</a>
</li>
<li>
<a href='#/'>Link</a>
</li>
<li>
<a href='#/'>Link</a>
</li>
</ul>
</nav>
</aside>
<!-- End Sidebar -->
<!-- Begin Content -->
<p class='content'>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae
est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis
tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis. Praesent dapibus, neque id cursus faucibus, tortor neque egestas augue, eu vulputate magna eros eu erat. Aliquam erat volutpat. Nam dui mi, tincidunt quis, accumsan
porttitor, facilisis luctus, metus</p>
<!-- End Content -->
</article>
<!-- End Container -->
<footer>
<address>
123 Main St.<br>
Springfield, IL 12345<br>
admin#mail.com
</address>
</footer>
</section>
</main>
</body>
</html>
First Solution using float on Desktop and using flex-direction on mobile Will give the result you want.
.sidebar {
float: right;
border: 1px solid;
width: 200px;
}
#media (max-width:767px) {
p,
.sidebar {
float: none;
width: auto;
}
.main {
display: flex;
width: 100%;
flex-direction: column-reverse;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="main">
<div class="sidebar"> <h1>Side bar</h1>
molestiae recusandae placeat corporis earum assumenda dolorem! Earum necessitatibus tempora enim nisi officiis in. Ducimus illo placeat eveniet.</div>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque explicabo aspernatur delectus voluptate, nesciunt quibusdam ab reprehenderit, non et temporibus. Aut commodi, voluptates nulla deleniti pariatur vitae vel eos sit asperiores aliquid,
molestiae recusandae placeat corporis earum assumenda dolorem! Earum necessitatibus tempora enim nisi officiis in. Ducimus illo placeat eveniet.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque explicabo aspernatur delectus voluptate, nesciunt quibusdam ab reprehenderit, non et temporibus. Aut commodi, voluptates nulla deleniti pariatur vitae vel eos sit asperiores aliquid,
molestiae recusandae placeat corporis earum assumenda dolorem! Earum necessitatibus tempora enim nisi officiis in. Ducimus illo placeat eveniet.Lorem ipsum dolor sit amet, consectetur adipisicing elit. Doloremque explicabo aspernatur delectus voluptate, nesciunt quibusdam ab reprehenderit, non et temporibus. Aut commodi, voluptates nulla deleniti pariatur vitae vel eos sit asperiores aliquid,
molestiae recusandae placeat corporis earum assumenda dolorem! Earum necessitatibus tempora enim nisi officiis in. Ducimus illo placeat eveniet.</p>
</div>
</div>
Helping Credits goes to #zer00ne
Second Solution if not using text to wrap under sidebar Using flex we can achieve this. As it has many advantages of playing with its properties without changing HTML structure and its more mature then float
.flex-container {
display: flex;
flex-direction: column;
}
.main {
width: 100%;
order: 1;
padding: 0 1em;
}
.sidebar-aside {
width: 100%;
order: 2;
padding: 0 1em;
background-color: #cff;
}
#media (min-width: 40em) {
.flex-container {
flex-direction: row;
}
.main {
flex: 1;
order: 1;
}
.sidebar-aside {
width: 15em;
order: 2;
}
}
<div class="flex-container">
<main class="main">
<article>
<h1>Main Title</h1>
<p>Some Content to fill the page.</p>
<h2 id="topic-1">Topic 1</h2>
<p>Info</p>
<h2 id="topic-2">Topic 2</h2>
<p>Info</p>
<h2 id="topic-3">Topic 3</h2>
<p>Info</p>
</article>
</main>
<aside class="sidebar-aside">
<h3>Side Bar</h3>
<h4>Sidebar Title</h4>
<p>Lorem epsum text is a dummy text</p>
</aside>
</div>
You can change the order on different screens that which div comes
first
It can be achieved using css grid
/* Here 2fr for main text and 1fr for side bar */
grid-template-columns: 2fr 1fr;
For screen size 600px or less
/* For mobile devices, it will be 1/1 grid */
grid-template-columns: 1fr;
*{
padding: 0;
margin: 0;
}
.container{
background: #f2f2f2;
padding: 10px;
height: 100vh;
}
.layout{
display: grid;
/* Actual style width 2 grid layout */
grid-template-columns: 2fr 1fr;
padding:5px;
}
.main-text{
padding: 20px;
}
.side-bar{
border: 2px solid #444;
}
/* For mobile devices with 1f 1/1 grid */
#media (max-width:600px){
.layout{
grid-template-columns:1fr;
}
}
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="container">
<h3>Resize screen for responsive</h3>
<div class="layout">
<div class="main-text">
<h2>Main text</h2>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ultrices mollis cursus. Vestibulum aliquam, lorem quis porta sodales, diam mi tincidunt quam, vitae consequat erat neque in turpis. Nam massa libero, feugiat ut laoreet eu, interdum et erat. Morbi quis suscipit nunc, blandit congue sapien. Aenean faucibus nisi sit amet quam interdum, eget mollis enim rutrum. Etiam viverra vel magna quis rutrum. Maecenas ipsum urna, feugiat sed sagittis id, vehicula eu enim. Ut commodo odio vitae nibh posuere blandit. Nunc aliquam metus vitae vehicula tempus. Vivamus semper pharetra felis mollis pellentesque. Vestibulum quis velit feugiat, blandit tortor a, mattis turpis. Mauris varius nisl id ultricies tempus. Vivamus imperdiet euismod pellentesque. Nullam pretium elit id semper convallis.
</div>
<div class="side-bar">
<h2>Side bar</h2>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce ultrices mollis cursus. Vestibulum aliquam, lorem quis porta sodales, diam mi tincidunt quam, vitae consequat erat neque in turpis. Nam massa libero, feugiat ut laoreet eu, interdum et erat. Morbi quis suscipit nunc, blandit congue sapien. Aenean faucibus nisi sit amet quam interdum, eget mollis enim rutrum. Etiam viverra vel magna quis rutrum.
</div>
</div>
</div>
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<style>
body {
font-family: sans-serif;
}
.app {
display: flex;
justify-content: flex-start;
align-items: stretch;
}
.main-text {
flex-basis: 70%;
background-color: #ddd;
min-height: 200px;
}
.sidebar {
flex-basis: 30%;
background-color: #1a1a1a;
color: white;
min-height: 100px;
}
#media only screen and (max-width: 600px) {
body {
background-color: lightblue;
}
.app {
flex-wrap: wrap;
}
.main-text {
flex-basis: 100%;
}
.sidebar {
flex-basis: 100%;
}
}
</style>
</head>
<body>
<div class="app" id="app">
<div class="main-text">
Main Text
</div>
<div class="sidebar">
SideBar
</div>
</div>
</body>
</html>
simple solution using flexbox, no javascript involved
class main-text and sidebar refer to respective components
height and background colors are added just for the visual effect,they are not necessary for the solution to work
Flexbox solution:
html:
<div class='content'>
<div class='main'><p> lorem ipsu... </p></div>
<div class='sidebar'><p> lorem ipsu ... </p></div>
</div>
css:
.container{
display: flex;
flex-wrap: wrap;
}
.main{
order: 1;
width:70%;
}
.sidebar{
order:2;
width:30%;
}
#media (max-width:600px){
.main{
width:100%;
}
}
Idea is that the main simply takes up the full width, forcing the sidebar down below it.
I would like to recreate the iTunes album view effect on the web and it must be responsive. I made an animated GIF to show the desired effect: http://files.katart.com/sgDkRGI
I've started a codepen using flexbox, but I can't seem to get the tabs to stay at the top. You can view it here: https://codepen.io/katartgraphics/pen/pWvNrP
Here is the markup:
jQuery(function($) {
$('.tab').on('click', function() {
$(this).siblings('.tab-content').slideUp();
$(this).next().slideDown();
});
});
.tabs-wrapper {
margin: 48px auto;
text-align: center;
}
.tab-container {
max-width: 960px;
margin: auto;
padding: 0 24px;
}
.tab > span {
display: block;
width: 100%;
height: 42px;
max-width: 280px;
margin: auto;
padding: 0 20px;
color: #555;
font-size: 14px;
text-transform: uppercase;
font-weight: 600;
line-height: 42px;
border: 1px solid #fff;
border-bottom: none;
background-color: whitesmoke;
box-sizing: border-box;
}
.tab-content {
display: none;
padding-top: 1rem;
padding-bottom: 1rem;
text-align: left;
background-color: tomato;
}
.tab-content > *:first-child { margin-top: 0; }
.tab-content > *:last-child { margin-bottom: 0; }
#media (min-width: 600px) {
.tabs-wrapper {
position: relative;
display: flex;
flex-flow: row wrap;
justify-content: center;
}
.tab {
positiion: relative;
top: 0;
flex: 0 1 auto;
}
.tab-content {
position: relative;
top: 0;
flex: 1 1 100%;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="tabs-wrapper">
<div class="tab"><span>Tab 1</span></div>
<div id="tab1" class="tab-content">
<div class="tab-container">
<h4>Tab 1 Content</h4>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Etiam porta sem malesuada magna mollis euismod. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
</div>
</div>
<div class="tab"><span>Tab 2</span></div>
<div id="tab2" class="tab-content">
<div class="tab-container">
<h4>Tab 2 Content</h4>
<p>Curabitur blandit tempus porttitor. Sed posuere consectetur est at lobortis. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
</div>
<div class="tab"><span>Tab 3</span></div>
<div id="tab3" class="tab-content">
<div class="tab-container">
<h4>Tab 3 Content</h4>
<p>Maecenas faucibus mollis interdum. Nulla vitae elit libero, a pharetra augue. Maecenas sed diam eget risus varius blandit sit amet non magna. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
</div>
</div>
<div class="tab"><span>Tab 4</span></div>
<div id="tab4" class="tab-content">
<div class="tab-container">
<h4>Tab 4 Content</h4>
<p>Nulla vitae elit libero, a pharetra augue. Etiam porta sem malesuada magna mollis euismod. Aenean lacinia bibendum nulla sed consectetur. Curabitur blandit tempus porttitor. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Cras mattis consectetur purus sit amet fermentum. Cras mattis consectetur purus sit amet fermentum.</p>
</div>
</div>
</div>
<h2>Other Content</h2>
<div>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quis sapiente quod unde, dicta asperiores ipsa nam eius earum quisquam natus tempore molestias necessitatibus consequuntur id ab illum modi assumenda reprehenderit!</div>
<div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Sed eligendi commodi facilis qui aut totam ipsam neque quod tempore omnis corrupti quaerat tenetur labore nesciunt, eum pariatur molestias velit a!</div>
<div>Lorem ipsum dolor sit amet consectetur adipisicing elit. Laudantium sequi unde iure iste aperiam ipsum officia temporibus consequuntur a pariatur aliquid, autem error, velit nam ad vitae eius deleniti cum.</div>
This question already has answers here:
How to create fluid trapezoid image with css?
(3 answers)
Closed 6 years ago.
What is the best way to create a diagonal shape like this with pure CSS maybe only using :after and :before pseudo elements on the content div? Thanks.
maybe it:
.content {
position: relative;
perspective: 100vw;
padding: 30px;
}
.content::before {
content: '';
position: absolute;
z-index: -1;
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 130%;
background: tomato;
transform-origin: 100% 50%;
transform: translate(-25%) rotateY(-20deg);
outline: 1px solid transparent;
}
<div class="content">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Repudiandae, laudantium.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptate voluptatum recusandae quos soluta impedit! Deleniti facere enim, quia ut quisquam.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deleniti eligendi dignissimos adipisci voluptatem voluptate ex maiores consequuntur, cum ducimus voluptatum, ratione similique asperiores reiciendis, odit quis sed. Reprehenderit doloribus, delectus.
</div>
One way is to set a background on a container and rotate with a CSS transform.
Here's a simple example, use as many overlapping containers as needed:
body {
margin: 0;
overflow-x: hidden;
font-family: monospace;
color: #fff;
}
.container {
width: 110vw;
margin-top:10vh;
margin-left: -10vw;
padding-left: 10vw;
background: red;
box-shadow: 0 0 15px rgba(0, 0, 0, .33);
transform: rotate(-5deg);
}
.container-inner {
padding: 10vw;
max-width: 80vw;
transform: rotate(5deg);
}
h1 {
margin-left: 10%;
padding-top: 50px;
}
<div class="container">
<h1>Diagonal Background</h1>
<div class="container-inner">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo. Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi, condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim ac dui. Donec non enim in turpis pulvinar facilisis. Ut felis.
</p>
</div>
</div>
Here is my codepen with the problem : http://codepen.io/Golgota/pen/gwvGGj
And my CSS :
.bloc {
background-color:white;
float:left;
width:100%;
margin: 10px;
padding: 10px;
height: 500px;
}
img {
max-width:100%;
max-height:100%;
}
#media all and (min-width: 40em) {
.bloc {
float: left;
width: 31%;
margin: 10px;
height: 500px;
}
}
I have 3 responsive div .bloc I would like to keep them at the same height. The problem comes from the images which have different sizes.
Is there a way to have 3 .bloc with the same height without changing the images' resolutions or scrolling ?
Cheers !
/* item styles */
.item-image {
position: relative;
overflow: hidden;
padding-bottom: 50%;
border: 1px solid #ddd;
}
.item-image img {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.item-content {
padding: 15px;
background: #72cffa;
}
.item-text {
position: relative;
overflow: hidden;
height: 100px;
}
/* centering styles for jsbin */
html,
body {
width: 100%;
height: 100%;
}
html {
display: table;
}
body {
display: table-cell;
vertical-align: middle;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Css aspect ratio to have images of same height</title>
<meta name="description" content="Css aspect ratio to have images of same height">
<!-- include bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-xs-4 col-sm-4">
<div class="item-image">
<img src="https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg" class="img-responsive">
</div>
<div class="item-content">
<div class="item-text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
</div>
</div>
<div class="col-xs-4 col-sm-4">
<div class="item-image">
<img src="http://s11.favim.com/orig/160919/forum-communaute-topic-9808-hd-putlocker-watch-hell-or-high-water-online-full-movie-1080p-Favim.com-4740061.jpeg" class="img-responsive">
</div>
<div class="item-content">
<div class="item-text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
</div>
</div>
</div>
<div class="col-xs-4 col-sm-4">
<div class="item-image">
<img src="http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg" class="img-responsive">
</div>
<div class="item-content">
<div class="item-text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas nec velit nulla. Cras finibus mollis dolor, ac rhoncus diam. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin gravida iaculis orci eget malesuada. Morbi pulvinar, purus sit amet porta laoreet, quam orci fermentum leo, in interdum ligula elit id magna. Nam justo massa, ultrices eget dictum vitae, porttitor eget eros.
</div>
</div>
</div>
</div>
</div>
</body>
</html>
you can use the object fit, but check the support first,
you can do this,
body {
background-color: orange;
padding: 5%;
margin: auto;
box-sizing: border-box;
}
.block-holder .bloc {
background-color: white;
float: left;
width: 32.66%;
padding: 10px;
height: 100%;
margin: 0;
}
.block-holder .bloc:not(:first-child):not(:last-child){
margin: 0 1%;
}
img {
width: 100%;
height: 50vh;
object-fit: cover;
}
*, *:before, *:after {
box-sizing: border-box;
}
<div class="block-holder">
<div class="bloc">
<img src="https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg">
<h2>Lorem ipsum</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Expedita itaque ipsa sit quibusdam optio cumque labore necessitatibus. Eaque soluta ut excepturi rerum repudiandae harum nisi doloremque cupiditate exercitationem voluptatem tempora.
<p>
</div>
<div class="bloc">
<img src="http://s11.favim.com/orig/160919/forum-communaute-topic-9808-hd-putlocker-watch-hell-or-high-water-online-full-movie-1080p-Favim.com-4740061.jpeg" />
<h2>Lorem ipsum</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Expedita itaque ipsa sit quibusdam optio cumque labore necessitatibus. Eaque soluta ut excepturi rerum repudiandae harum nisi doloremque cupiditate exercitationem voluptatem tempora.
<p>
</div>
<div class="bloc">
<img src="http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg" />
<h2>Lorem ipsum</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Expedita itaque ipsa sit quibusdam optio cumque labore necessitatibus. Eaque soluta ut excepturi rerum repudiandae harum nisi doloremque cupiditate exercitationem voluptatem tempora.
<p>
</div>
</div>
Try this. I just changed the image min-height into pixels rather than %.
body {
background-color:orange;
padding: 5%;
margin:auto;
}
.bloc {
background-color:white;
float:left;
width:100%;
margin: 10px;
padding: 10px;
height: 500px;
}
img {
max-width:100%;
min-height: 270px;
}
#media all and (min-width: 40em) {
.bloc {
float: left;
width: 31%;
margin: 10px;
height: 500px;
}
}
<div class="bloc">
<img src="https://pixabay.com/static/uploads/photo/2015/10/01/21/39/background-image-967820_960_720.jpg">
<h2>Lorem ipsum</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Expedita itaque ipsa sit quibusdam optio cumque labore necessitatibus. Eaque soluta ut excepturi rerum repudiandae harum nisi doloremque cupiditate exercitationem voluptatem tempora.
<p>
</div>
<div class="bloc">
<img src="http://s11.favim.com/orig/160919/forum-communaute-topic-9808-hd-putlocker-watch-hell-or-high-water-online-full-movie-1080p-Favim.com-4740061.jpeg"/>
<h2>Lorem ipsum</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Expedita itaque ipsa sit quibusdam optio cumque labore necessitatibus. Eaque soluta ut excepturi rerum repudiandae harum nisi doloremque cupiditate exercitationem voluptatem tempora.
<p>
</div>
<div class="bloc">
<img src="http://www.menucool.com/slider/jsImgSlider/images/image-slider-2.jpg"/>
<h2>Lorem ipsum</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Expedita itaque ipsa sit quibusdam optio cumque labore necessitatibus. Eaque soluta ut excepturi rerum repudiandae harum nisi doloremque cupiditate exercitationem voluptatem tempora.
<p>
</div>