Reputation: 95
With a colleague of mine, we wanted to run a behavioural experiment that involve a fake purchase of virtual goods on a shop webpage. We designed the experiment on OTree (so on Python), but we needed Django and especially some html/css code to correctly place the images and texts on the webpage.
We managed to place the images and text as we wanted, to get something like that (the blue squares are just placeholders for the images):
The problem is that as soon as we change the window size, all the images and text just move on their own.
Here's a part of the code (not including everything because for now, we're just trying to get first the text in place and to understand the logic of it).
Here's the CSS:
<style>
body {
background-image: url('https://i.imgur.com/lVtlHWx.png');
background-repeat: no-repeat;
background-attachment: fixed;
background-size: 100% 100%;
}
</style>
and the HTML:
<div style="top: 99px; left: 99px;position: absolute; z-index: 1;visibility: visible;">
<h1 style="position: relative; color: #f0f0f0; font-family: Papyrus,monospace;">Welcome to the shop</h1>
<h3 style="position: relative;color: #f0f0f0; font-family: Papyrus,monospace;">Round 1/10</h3>
<p style="position: relative;top:9.5cm; left:6.5cm; color: #f0f0f0; font-family: Papyrus,monospace;font-size:25px;">5 Rubis</p>
<p style="position: relative;top:9.5cm; left:18cm; color: #f0f0f0; font-family: Papyrus,monospace;font-size:25px;">15 Rubis</p>
<p style="position: relative;top:9.5cm; left:29.5cm; color: #f0f0f0; font-family: Papyrus,monospace;font-size:25px;">25 Rubis</p>
<p style="position: relative;top:9.5cm; left:41cm; color: #f0f0f0; font-family: Papyrus,monospace;font-size:25px;">50 Rubis</p>
<p style="position: relative;top:16cm; left:6.5cm; color: #f0f0f0; font-family: Papyrus,monospace;font-size:25px;">5 Rubis</p>
<p style="position: relative;top:9.5cm; left:18cm; color: #f0f0f0; font-family: Papyrus,monospace;font-size:25px;">15 Rubis</p>
<p style="position: relative;top:9.5cm; left:29.5cm; color: #f0f0f0; font-family: Papyrus,monospace;font-size:25px;">25 Rubis</p>
<p style="position: relative;top:9.5cm; left:41cm; color: #f0f0f0; font-family: Papyrus,monospace;font-size:25px;">50 Rubis</p>
We're complete beginners in HTML/CSS and I think we bite more than we could chew. I followed and tried some answers but nothing really helped to resize every element with respect to the window size. Perhaps it is due to positioning the text? I still struggle to really understand how css places elements when their position are absolute or relative. We are in dire need of help on this matter, and would be immensely grateful if someone could solve our issue.
Upvotes: 0
Views: 2570
Reputation: 2619
I couldn't resist, here is what you should really do: abandon your backdrop that constrains layout, and use a real HTML layout instead, with textures to help achieving the effect you want.
This snippet should be viewed in full page mode
:root {
--iron-texture: url('https://www.outworldz.com/SeamlessTextures/master/Metal/iron_diffuse.png');
--wood-texture: url('https://images.designtrends.com/wp-content/uploads/2015/12/22092207/Seamless-Wooden-Floor-Texture.jpg?width=600');
}
html { padding: 0; margin: 0; height: 100%;}
body {
box-sizing: border-box;
padding: 1rem;
margin: 0;
min-height: 100%;
background: black;
color: white;
font-family: Papyrus, monospace;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
}
.shop {
box-sizing: border-box;
width: 100%;
max-width: 1200px;
background: var(--wood-texture);
background-size: 30%;
color: #ccc;
padding: 1rem;
}
.shop header {
position: relative;
display: flex;
flex-direction: column;
gap: 1em;
}
.shop h1,
.shop p {
padding: 0;
margin: 0;
}
.shop h1 {
font-size: 32px;
}
.shop .round {
position: absolute;
top: 0;
right: 0;
font-size: 28px;
}
.iron-style {
background: var(--iron-texture);
border: 4px solid #1a1a1a;
border-top-color: #2a2a2a;
border-right-color: #2a2a2a;
}
.shop .wallet {
font-size: 20px;
font-weight: bold;
box-sizing: border-box;
width: 20em;
align-self: center;
text-align: center;
padding: .5em;
border-radius: 1.5em;
}
.shop main {
margin-top: 1rem;
padding-bottom: 1rem;
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 2rem 1rem;
border: 1rem solid #222;
border-image: var(--iron-texture);
border-image-repeat: round;
border-image-slice: 20;
box-shadow: inset -3px 3px 3px #111,
inset 3px -3px 5px #333;
}
.product {
display: flex;
flex-direction: column;
}
.pic-layout {
height: 100px;
min-width: 150px;
padding: 1rem;
display: flex;
align-items: center;
justify-content: center;
}
.pic-layout img {
max-width: 150px;
max-height: 100px;
background: #aaf;
outline: 5px solid #333;
}
.price {
width: 6em;
padding: .3em 1em;
border-radius: .5em;
align-self: center;
text-align: center;
}
@media screen and (max-width: 1000px) {
.shop main {
grid-template-columns: repeat(3, 1fr);
}
}
@media screen and (max-width: 700px) {
.shop main {
grid-template-columns: repeat(2, 1fr);
}
.shop .round {
position: static;
align-self: flex-end;
}
}
<section class="shop">
<header>
<h1>Welcome to the Shop</h1>
<p class="round">Round 1/10</p>
<p class="wallet iron-style">You have 1000 tokens</p>
</header>
<main>
<div class="product" id="product-1">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods1/150/100" />
</div>
<div class="price iron-style">5 Rubis</div>
</div>
<div class="product" id="product-2">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods2/150/100" />
</div>
<div class="price iron-style">25 Rubis</div>
</div>
<div class="product" id="product-3">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods3/150/100" />
</div>
<div class="price iron-style">15 Rubis</div>
</div>
<div class="product" id="product-4">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods4/150/100" />
</div>
<div class="price iron-style">42 Rubis</div>
</div>
<div class="product" id="product-5">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods5/150/100" />
</div>
<div class="price iron-style">120 Rubis</div>
</div>
<div class="product" id="product-6">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods6/150/100" />
</div>
<div class="price iron-style">33 Rubis</div>
</div>
<div class="product" id="product-7">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods7/150/100" />
</div>
<div class="price iron-style">6 Rubis</div>
</div>
<div class="product" id="product-8">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods8/150/100" />
</div>
<div class="price iron-style">44 Rubis</div>
</div>
<div class="product" id="product-9">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods9/150/100" />
</div>
<div class="price iron-style">99 Rubis</div>
</div>
<div class="product" id="product-10">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods10/150/100" />
</div>
<div class="price iron-style">1 Rubis</div>
</div>
<div class="product" id="product-11">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods11/150/100" />
</div>
<div class="price iron-style">23 Rubis</div>
</div>
<div class="product" id="product-12">
<div class="pic-layout">
<img src="https://picsum.photos/seed/prods12/150/100" />
</div>
<div class="price iron-style">16 Rubis</div>
</div>
</main>
</section>
This time I structured the shop with one wrapper div per product, but I could have avoided that using the same kind of grid as in my previous answer.
There are no vertical separators as CSS grid
does not allow for inner borders (yet). If this is a requirement, the <main>
element should be replaced with a <table>
, which allows for all kinds of borders.
grid
has the advantage of offering responsive layout using @media
queries. That's why you can see all products on only 2 columns in the sample above, unless you enlarge it to full page.
Upvotes: 1
Reputation: 2619
This is a typical case where using a table or better, CSS grid positioning would save you a lot of headaches.
Positioning according to measurements on your background image gives the following:
:root {
--display-scale: .5;
}
body {
padding: 10px;
background: black;
overflow: hidden; /* disable scrolling */
}
.wrapper {
transform: scale(var(--display-scale));
-webkit-transform: scale(var(--display-scale));
transform-origin: 0 0;
width: 1884px;
height: 1076px;
background: url('https://i.imgur.com/lVtlHWx.png') no-repeat;
position: relative;
font-family: Papyrus, monospace;
color: #f0f0f0;
}
.wrapper * {
box-sizing: border-box;
}
.wrapper h1 {
position: absolute;
padding: 0;
top: 10px;
left: 10px;
font-size: 48px;
}
.wrapper h3 {
position: absolute;
padding: 0;
top: 10px;
right: 10px;
font-size: 36px;
}
.wrapper .wallet {
position: absolute;
top: 42px;
height: 46px;
left: 720px;
right: 682px;
font-size: 36px;
display: flex;
align-items: center;
justify-content: center;
}
.wrapper .my-grid {
position: absolute;
/*background: #ff000055;*/
top: 228px;
left: 110px;
right: 82px;
bottom: 82px;
padding: 0;
column-gap: 38px;
display: grid;
grid-template-columns: 384px 402px 406px 1fr;
grid-template-rows: 196px 50px 202px 50px 202px 50px;
grid-auto-flow: column;
}
.my-grid .prod-image {
/*background: #00ff0055;*/
display: flex;
align-items: center;
justify-content: center;
}
.my-grid img {
display: block;
width: 180px;
height: 130px;
background: #5555ff;
outline: 5px solid black;
}
.my-grid .price {
/*background: #0000ff55;*/
font-size: 24px;
margin 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
}
<div class="wrapper">
<h1>Welcome to the shop</h1>
<h3>Round 1/10</h3>
<p class="wallet">You have 1000 tokens</p>
<div class="my-grid">
<div class="prod-image"><img class="pic" /></div>
<p class="price">5 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">15 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">25 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">50 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">5 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">15 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">25 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">50 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">50 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">50 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">50 Rubis</p>
<div class="prod-image"><img class="pic" /></div>
<p class="price">50 Rubis</p>
</div>
</div>
Use the --display-scale: .5
variable to adjust display size
Upvotes: 1
Reputation: 707
You can achieve your desired results with css Grid and Flexbox.
This page content:
<body>
<div id="head">
<h1>Welcome to the shop</h1>
<h3>Round 1/10</h3>
</div>
<div id="labels_container">
<div class="item"><p class="label">5 Rubis</p></div>
<div class="item"><p class="label">15 Rubis</p></div>
<div class="item"><p class="label">25 Rubis</p></div>
<div class="item"><p class="label">50 Rubis</p></div>
<div class="item"><p class="label">5 Rubis</p></div>
<div class="item"><p class="label">15 Rubis</p></div>
<div class="item"><p class="label">25 Rubis</p></div>
<div class="item"><p class="label">50 Rubis</p></div>
<div class="item"><p class="label">5 Rubis</p></div>
<div class="item"><p class="label">15 Rubis</p></div>
<div class="item"><p class="label">25 Rubis</p></div>
<div class="item"><p class="label">50 Rubis</p></div>
</div>
</body>
With this css styling:
body {
background-image: url('./lVtlHWx.png');
background-repeat: no-repeat;
background-attachment: fixed;
background-size: 100% 100%;
display: grid;
grid-template-rows: [gstart]1fr[gmid] 5fr[gend];
height: 100vh;
width: 100vw;
}
#head {
grid-row: gstart / gmid;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#head * {
margin: 0;
}
#labels_container {
grid-row: gmid / gend;
margin-top: 3vh;
margin-left: 5vw;
margin-right: 7vw;
margin-bottom: 9.5vh;
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(3, 1fr);
column-gap: 2.5%;
}
.item .label {
margin: 0;
margin-bottom: 1vh;
}
* {
color: #f0f0f0;
font-family: Papyrus, monospace;
}
h1, h3 {
position: relative;
}
.item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: flex-end;
}
.label {
font-size: 25px;
}
should do what you want.
Note: You might also find it beneficial to make the interface a div in your page with a constant aspect ratio, because you have an image as the backdrop for the entire interface. Having this image deform makes styling the page awkward. That being said, the styles above should work with your current setup.
Upvotes: 1