I'm trying to make a window that will display a number of show listings, panning through each with left and right scroll buttons. The problem is, when I place two listing layouts within the frame, it doesn't add them side by side at their full size with a scrollbar as I would expect. Instead, it distorts both so they will fit in the same space.
EDIT: I thought it might be prudent to mention that the ultimate goal here is to get a list of show objects from a server, and the number can vary. So, the width of the div holding them will have to adapt to the change.
Here is what I'm after, with one in view:
Here is what is actually happening:
The color gradient is only there so I can see what I'm doing. Once I'm sure they're panning correctly, it'll be changed to transparent. Below is my code. If anyone can offer any advice, I'd appreciate it.
Shows.js:
import {useState} from 'react';
import styles from './Shows.module.css';
const Shows = () => {
const Show = (details) => {
return (
<div className={styles.showMain}>
<div className={styles.posterFrame} style={null /* SET BACKGROUND IMAGE HERE, COVER??? */}/>
<div className={styles.textFrame}>
TEST
</div>
</div>
)
}
return (
<div className={styles.main} id="shows">
<div className={styles.container}>
<div className={styles.banner}>
<h1 className={styles.bannerText}>UPCOMING SHOWS</h1>
</div>
<div className={styles.scrollContainer}>
<div className={styles.scrollButton}><</div>
<div className={styles.showBody}>{Show(null)}</div>
<div className={styles.showBody}>{Show(null)}</div>
<div className={styles.scrollButton}>></div>
</div>
</div>
</div>
)
}
export default Shows
Shows.module.css:
.main {
display: flex;
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3)), linear-gradient(112.78deg, rgba(183, 35, 35, 0.5) 12.87%, rgba(51, 169, 236, 0.5) 52.53%, rgba(74, 183, 35, 0.5) 97.84%), url("../../public/images/concert1.jpg");
background-size: cover;
height: 100vh;
width: 100vw;
justify-content: center;
align-items: center;
}
/* ---------------- Scrolling frame ---------------- */
.container {
position: relative;
display: flex;
flex-direction: column;
background: rgba(0,0,0,.5);
height: 82.5%;
width: 85%;
margin-top: 6%;
}
.scrollContainer {
display: flex;
flex-direction: row;
height: 90%;
width: 100%;
overflow: hidden;
}
.banner {
background: rgba(0,0,0,0.45);
display: flex;
height: 10%;
width: 100%;
align-items: center;
justify-content: center;
}
.bannerText {
font-weight: lighter;
color: rgba(50, 236, 191, 1);
text-shadow: 2px 2px rgba(183, 35, 35, 1);
}
.scrollButton {
display: flex;
align-items: center;
justify-content: center;
background: rgba(0,0,0,0.25);
color: white;
height: 100%;
width: 5%;
transition-duration: .25s;
}
.scrollButton:hover {
background: rgba(0,0,0,0.45);
}
.showBody {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
background: rgba(0,0,0,0.25);
height: 100%;
width: 90%;
overflow: hidden;
}
/* ---------------- Show listing ---------------- */
.showMain {
height: 100%;
width: 100% !important;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background: linear-gradient(90deg, #FF0000 -9.27%, rgba(34, 255, 0, 1) 112.68%);
overflow: hidden;
}
.posterFrame {
height: 90%;
width: 35%;
background: rgba(0,0,0,0.65);
margin-right: 5%;
}
.textFrame {
height: 90%;
width: 50%;
background: rgba(0,0,0,0.65);
color: white;
}
.scrollContainer {
display: flex;
flex-direction: row;
height: 90%;
width: 100%;
overflow: hidden;
}
This not going to work, you need make it like so:
.scrollContainer {
display: flex;
flex-direction: row;
height: 90%;
//width: 100%; < wrong
//overflow: hidden; < wrong
overflow-x:auto;
flex-wrap:no-wrap;
}
Then
.showMain {
height: 100%;
//width: 100% !important;
width: 300px; // sorry I have to be specified
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
background: linear-gradient(90deg, #FF0000 -9.27%, rgba(34, 255, 0, 1) 112.68%);
overflow: hidden;
}
Alright, I figured it out. In combination with the suggestions here, which got me to the side by side display I was after, I placed the two Show items in a new div with the className showWindow. I set the CSS for the window as follows:
.showWindow {
width: 90%;
display: flex;
flex-direction: row;
overflow: auto;
}
This displays one at a time, gives me the scrollbar, and does not obstruct the scroll buttons. Thanks for helping me find the solution, everyone.
Update the css:
.scrollContainer {
...
overflow: auto;
}
.showBody {
...
flex: none;
}
.scrollButton {
...
flex: none;
}
.sliderContainer {
display: flex;
height: 100%;
}
Then wrap the content with a sliderContainer:
<div className={styles.sliderContainer}>
<div className={styles.scrollButton}><</div>
<div className={styles.scrollContainer}>
<div className={styles.showBody}>{Show(null)}</div>
<div className={styles.showBody}>{Show(null)}</div>
</div>
<div className={styles.scrollButton}>></div>
</div>
And it works fine.
Related
counter.js
import "./Counter.css";
const Counter = (props) => {
return (
<div className="counter">
<h1>{`Counter ${props.count}`}</h1>
<div className="counter__buttons">
<button onClick={props.incrementCounter}>Increment</button>
<button onClick={props.decrementCounter}>Decrement</button>
</div>
</div>
);
};
Counter.css
.counter {
display: flex;
color: white;
align-items: center;
width: 100%;
height: 100%;
}
.counter > .counter__buttons > button {
color: black;
background-color: grey;
margin: 10px;
padding: 30px;
border: 0;
border-radius: 10px;
}
i want to move the buttons below counter and place the counter and buttons in the center of the page how to change it , display : flex in counter should not be removed
Would something like this work? You can set the flex-direction of a wrapping div to column and set the second div (in your case your buttons) back to flex-direction: row and finally just center it with margin: 0 auto.
<div id="wrap">
<div id="one">1</div>
<div id="two">2
<div id="three">3</div>
<div id="four">4</div>
</div>
</div>
#wrap {
display: flex;
flex-direction: column;
}
#two {
display: flex;
flex-direction: row;
margin: 0 auto;
}
Do you want something like this?
.page {
background: black;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
}
.counter {
display: flex;
flex-direction: column; /* add this */
color: white;
align-items: center;
/* width: 100%;*/
/* height: 100%;*/
}
.counter > .counter__buttons > button {
color: black;
background-color: grey;
margin: 10px;
padding: 30px;
border: 0;
border-radius: 10px;
}
<div class="page">
<div class="counter">
<h1>Counter 5</h1>
<div class="counter__buttons">
<button onClick={props.incrementCounter}>Increment</button>
<button onClick={props.decrementCounter}>Decrement</button>
</div>
</div>
</div>
If so, you can make your whole page a flex container and use justify-content and align-items just like you did it for the .counter.
(I did HTML instead of JSX so I could add the snippet easier... don't forget to make changes in your own code)
I have achieved the effect I desire with the code below, but it only seems to work in Firefox and Edge. In Chrome, the elements are stacked as desired, but there is no horizontal scroll bar so the right most items are hidden and inaccessible to the user.
As you can see, the header and footer stay in place and the my-app element is the only part that is scrollable. The items on the left appear above the ones to the right and the items all the way to the right are available through scrolling.
body {
margin: 0;
height: 100vh;
}
my-app {
display: flex;
height: 100vh;
flex-direction: column;
}
header, footer {
height: 25px;
background-color: black;
color:white;
}
main {
display: flex;
flex-direction: row-reverse;
flex-grow: 1;
justify-content: flex-end;
margin: 0;
overflow-x: auto;
width: 100vw;
}
.card {
--card-height: 200px;
--card-width: 250px;
align-items: center;
background: linear-gradient(rgba(179, 156, 95, 1), rgba(150, 117, 24, 1));
border-radius: 5px;
box-shadow: 1.5rem 0 2rem #222;
color: #000;
display: flex;
flex-direction: column;
height: var(--card-height);
justify-content: center;
min-width: var(--card-width);
position: relative;
text-align: center;
transition: all .15s ease-in-out;
transition: margin .3s ease-in-out;
width: var(--card-width);
}
.card:not(:last-of-type) {
margin-left: calc(var(--card-width) * -.5);
}
.card:hover:not(:last-of-type) {
margin-left: 0;
}
<my-app>
<header>Header</header>
<main>
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
<div class="card">6</div>
<div class="card">7</div>
<div class="card">8</div>
<div class="card">9</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
<div class="card">13</div>
<div class="card">14</div>
<div class="card">15</div>
</main>
<footer>Footer</footer>
</my-app>
If I change the css applied to main to:
main {
...
flex-direction: row;
...
justify-content: flex-start;
...
}
Then the scroll bar appears, but the items aren't stacked correctly(the ones on the right overlay the ones on the left).
If I go one step further and add direction: rtl; to the main style as well, the layout works as expected, but the default scroll position is all the way to the right of the screen(which makes sense). I could probably keep this and add some javascript to change the scroll location on page load, but that all seems quite hacky. Is there a better way to achieve the layout I'm looking for that will work in Chrome, Firefox and Edge?
Looks like an additional wrapper solves your problem:
body {
margin: 0;
height: 100vh;
}
my-app {
display: flex;
height: 100vh;
flex-direction: column;
}
header,
footer {
height: 25px;
background-color: black;
color: white;
}
main {
flex-grow: 1;
margin: 0;
overflow-x: auto;
width: 100vw;
}
.wrapper {
display: flex;
flex-direction: row-reverse;
justify-content: flex-end;
}
.card {
--card-height: 200px;
--card-width: 250px;
align-items: center;
background: linear-gradient(rgba(179, 156, 95, 1), rgba(150, 117, 24, 1));
border-radius: 5px;
box-shadow: 1.5rem 0 2rem #222;
color: #000;
display: flex;
flex-direction: column;
height: var(--card-height);
justify-content: center;
min-width: var(--card-width);
position: relative;
text-align: center;
transition: all .15s ease-in-out;
transition: margin .3s ease-in-out;
width: var(--card-width);
}
.card:not(:last-of-type) {
margin-left: calc(var(--card-width) * -.5);
}
.card:hover:not(:last-of-type) {
margin-left: 0;
}
<my-app>
<header>Header</header>
<main>
<div class="wrapper">
<div class="card">1</div>
<div class="card">2</div>
<div class="card">3</div>
<div class="card">4</div>
<div class="card">5</div>
<div class="card">6</div>
<div class="card">7</div>
<div class="card">8</div>
<div class="card">9</div>
<div class="card">10</div>
<div class="card">11</div>
<div class="card">12</div>
<div class="card">13</div>
<div class="card">14</div>
<div class="card">15</div>
</div>
</main>
<footer>Footer</footer>
</my-app>
I have set a flexbox to align my elements but my page fails to vertically center.
I can't figure out why since I have even a container for my page, I have ensure brut-size with viewport's units also.
So here my sandbox: https://codesandbox.io/s/rlk3j68pmq.
Here my reactjs snippet:
class App extends Component {
state = {
name: "",
message: "",
messageStock: []
}
render() {
return (
<div className={style.page}>
<div className={style.page_container}>
<div className={style.form_container}>
<form onSubmit={this.emitMessage} >
<input
name="message"
type="text"
placeholder="message"
value={this.state.message}
onChange={this.handleChange}
/>
<input type="submit" value="Send" />
</form>
</div>
<div
className={style.link}
>
<p>Go to </p>
<div prefetch href="/">
<a>/Home</a>
</div>
<br />
<p>Go to </p>
<div prefetch href="/letchat">
<a>/Letchat</a>
</div>
</div>
</div>
</div>
)
}
}
here my css snipet:
.page{
width: 100vw;
height: 100%;
min-height: 100vh;
background: rgb(219, 101, 255);
}
.page_container{
padding: 5vh 3vw;
}
.page .form_container{
height: 100%;
width: 100%;
display:flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.page form{
display:flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.page form input[type="text"]{
height: 10vh;
width: 30vw;
}
.message_box{
background: white;
height: 40vh;
width: 70vw;
margin:auto;
border:solid greenyellow;
margin-bottom: 5vh;
overflow: scroll;
}
.message_item{
margin: 2vh 0;
}
.link{
display:inline-block;
}
Any hint would be great,
thanks
To vertically align the content, you would need to add these last few lines in styles.module.css:
.page {
width: 100vw;
height: 100%;
min-height: 100vh;
background: rgb(219, 101, 255);
/* Added the following */
display: flex;
flex-direction: column;
align-items: center;
}
codesandbox
.page{
width: 100vw;
height: 100%;
min-height: 100vh;
background: rgb(219, 101, 255);
/*add following to center align content vertically */
display:flex;
align-items: center;/*vertically align page_container*/
justify-content:center/*horizontally align page_container*/
}
.page_container{
padding: 5vh 3vw;
/* add following to center align content of page_container horizontally*/
text-align:center
}
Add the above rules to styles.modules.css file.
Codesandbox link: https://codesandbox.io/s/olrvozl2z5?codemirror=1&fontsize=14
When using position: fixed, the browser will remove the original place the layout thing have. How to prevent it?
In my case, the actual fixed position of a search appbar act as
Expecting act as.
Simulating css code.
.search-appbar-container {
position: fixed;
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
height: 48px;
}
.lef-arrow-icon-container`
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
width: 60px;
`;
.search-textfiled-container`
display: flex;
flex: 1;
flex-direction: row;
align-items: center;
`;
.add-icon-container`
display: flex;
flex-direction: row;
align-items: center;
`;
.search-history-container {
display: flex;
flex-direction: column;
justify-content: center;
width: 100%;
margin-top: 5px;
}
.history-toggle-button`
position: relative;
width: 100%;
height: 48px;
background-color: transparent;
-webkit-box-sizing: border-box;
box-sizing: border-box;
border: none;
outline: none;
-webkit-appearance: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-tap-highlight-color: transparent;
`;
.history-icon-container`
position: absolute;
top: 11.5px;
left: 0;
width: 60px;
`;
.history-text-container`
position: absolute;
top: 11.5px;
left: 60px;
display: flex;
flex-direction: row;
align-items: center;
`;
Simulating html code.
<div>
<div class="search-appbar-container">
<div class="left-arrow-container>
...
</div>
<div class="search-textfield-container>
...
</div>
<div class="add-icon-container>
...
</div>
</div>
<div class="search-history-div">
<button class="history-toggle-button">
<div class="history-icon-container>
...
</div>
<div class="history-text-container>
...
</div>
</button>
</div>
</div>
EDIT
Have checkout all of my code, now I can find why this happened.
If the position of .search-appbar-container is static, the absolute position of history-icon-container and history-text-container are related the relative position of history-toggle-button, otherwise they are all related fixed position of search-appear-container.
you can set margin-top or padding-top to .search-history-div or set .search-history-div{position: fixed;top: 48px}
After searching and trying by myself, I have come out with a idea. If you want to keep fixed div with a block level, the proper way is to wrapper the same size parent div over it. Reflecting to my case, add the same width and height wrapper div upper search-appbar-container
.search-appbar-container-wrapper {
width: 100%;
height: 48px;
}
.search-appbar-container {
position: fixed;
...
width: 100%;
height: 48px;
}
...
<div class="search-appear-container-wrapper">
<div class="search-appbar-container">
...
</div>
</div>
...
This question already has an answer here:
Remove space (gaps) between multiple lines of flex items when they wrap
(1 answer)
Closed 4 years ago.
enter code hereI can't really explain it better than this code example.
https://codepen.io/anon/pen/BYeger
I want to make #thing_down_here touch #thing_up_here, but I can't figure out the right combination.
html, body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box
}
#parent {
width: 100vw;
height: 100vh;
background: cornsilk;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
#thing_up_here {
flex: 1 0 100%;
background: skyblue;
height: 80px;
}
#thing_down_here {
flex: 0 0 50%;
background: lightgreen;
height: 100px;
}
<div id="parent">
<div id="thing_up_here"></div>
<div id="thing_down_here"></div>
</div>
You need to use use the align-content property to set the distribution along the cross-axis.
html, body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box
}
#parent {
width: 100vw;
height: 100vh;
background: cornsilk;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-content: flex-start;
}
#thing_up_here {
flex: 1 0 100%;
background: skyblue;
height: 80px;
}
#thing_down_here {
flex: 0 0 50%;
background: lightgreen;
height: 100px;
}
<div id="parent">
<div id="thing_up_here"></div>
<div id="thing_down_here"></div>
</div>
Read more about align-content.
Add align-content: flex-start to #parent
This defines the default behaviour for how flex items are laid out along the cross axis on the current line. Think of it as the justify-content version for the cross-axis (perpendicular to the main-axis).
flex-start: cross-start margin edge of the items is placed on the cross-start line
The default is stretch which is causing your issue
More on it at https://css-tricks.com/snippets/css/a-guide-to-flexbox/
html, body {
margin: 0;
padding: 0;
}
* {
box-sizing: border-box
}
#parent {
width: 100vw;
height: 100vh;
background: cornsilk;
display: flex;
flex-wrap: wrap;
justify-content: center;
align-content: flex-start;
}
#thing_up_here {
flex: 1 0 100%;
background: skyblue;
height: 80px;
}
#thing_down_here {
flex: 0 0 50%;
background: lightgreen;
height: 100px;
}
<div id="parent">
<div id="thing_up_here"></div>
<div id="thing_down_here"></div>
</div>