I am trying to create a restaurant menu. I would like each menu item to be formatted as such:
Mozzarella Sticks ($9.95)
To do this I have the following html:
<h3 class="menu-item">Mozzarella Sticks</h3><p class="price">5.95</p>
I have the item name and price in different elements because I would like to make the price smaller, change the color, etc...
My problem is getting both elements to appear next to each other since h3 and p are both block elements. Here are the solutions I have come up with. Solution one:
.menu-item{
display: inline;
}
.price{
display: inline;
}
And adding a line break at the end of each entry:
<h3 class="menu-item">Mozzarella Sticks</h3><p class="price">5.95</p>
<br />
This works however I feel this is not the proper way to do this and that it should be done with CSS.
I have also considered the following, solution two:
<h3 class="menu-item">Mozzarella Sticks <span class="price">5.95</span></h3>
This would allow me style the price separate from the menu item, but including the price in the h3 still feels like an odd way to go about this.
Lastly, I have seen that you can set a width on both elements and then apply float: left; and float: right; but this messes up the spacing, as I would like the elements to appear right next to each other.
Any suggestions? Were any of the ways I listed a good way to about this or is there a better solution?
Try this grid layout. You can customize each block to your own liking.
You can add another column by inserting 1fr
.menu{
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto;
grid-template-areas: 'a b';
}
.menu-item{
grid-area: a;
text-align: center;
font-size: 20px;
}
.price{
grid-area: b;
text-align: center;
font-size: 18px;
}
<div class="menu">
<div class="menu-item">Mozzarella Sticks</div>
<div class="price"><i>($9.95)</i></div>
</div>
You can set widths as a percentages, let's say 80% and 20% respectively.
If you set display: inline-block you don't need to set any float. The elements keep having block properties but are kept inside the text flux like they were actual text.
Even though this works alone, i would suggest to also keep a better and cleaner semantic html division, like the ul showdev mentioned or at least a containing div for each couple.
You might consider creating an element for each item with children for the name and price.
Below, I'm using flexbox for item layout.
#menuItems {
margin: 0;
padding: 1em;
}
.menuItem {
margin: 0 0 1em;
display: flex;
}
.menuItemTitle {
flex: 0 0 150px;
margin: 0 1em 0 0;
font-size: 1em;
}
.menuItemPrice::before {
content: "$";
}
<ul id="menuItems">
<li class="menuItem">
<h3 class="menuItemTitle">Mozzarella Sticks</h3>
<span class="menuItemPrice">5.95</span>
</li>
<li class="menuItem">
<h3 class="menuItemTitle">Another Item</h3>
<span class="menuItemPrice">10.50</span>
</li>
<li class="menuItem">
<h3 class="menuItemTitle">Third Item with a Longer Name</h3>
<span class="menuItemPrice">10.50</span>
</li>
</ul>
My problem is getting both elements to appear next to each other since
h3 and p are both block elements. Here are the solutions I have come
up with. Solution one:
In general, if you want two block elements to appear next to each other without using the newer layout methods (flexbox and css grids). You can float the elements and then add a "clear fix" to those elements and here are two ways you do that.
Float the elements, Add an extra div, Add the clearfix
Float the elements, Add a CSS pseudo element "after", Add the clearfix
Method 1: Add extra div
<style type="text/css">
.clearfix{
display: block;
clear: both;
}
h3{
float:left;
}
p{
float:left;
}
</style>
<div class="my-container">
<h3>Hello</h3><p>World</p>
<div class="clearfix"></div>
</div>
Method 2: Add pseudo elem after
<style type="text/css">
.clearfix::after {
display: block;
clear: both;
}
h3{
float:left;
}
p{
float:left;
}
</style>
<div class="my-container clearfix">
<h3>Hello</h3><p>World</p>
</div>
Please note that on method 2, clearfix class was added to the container. Also, notice that a pseudo CSS element ::after was added to .clearfix.
This would allow me style the price separate from the menu item, but including the price in the h3 still feels like an odd way to go about this.
I think you are right. Building HTML should be semantic. Which basically means that your markup/code must be self-explaining or have meaning. In the context of what you are trying to achieve, h3 here (IMHO) doesn't suit what you are really trying to express or do. The reason I say that is because you are to display a list of "menu-items" and h3 by definition is a header so the element doesn't fit what it is trying to display. My recommendation is, instead of using h3, use a list instead, similar to the answer above. This would make your HTML code a lot more semantic and you can now use the other method you've mentioned without making it look weird (because span is inside of h3). It would look similar to the code below instead...
<ul id="menuItems">
<li class="menuItem">Mozzarella Sticks<span class="menuItemPrice">5.95</span</li>
</ul>
Btw, my recommendation above is just my opinion so please take it with a grain of salt. For more info about semantic HTML. You can check the links below
https://www.lifewire.com/why-use-semantic-html-3468271
https://www.w3schools.com/html/html5_semantic_elements.asp
Hope this helps! :)
Related
I simply want all of my p elements to be the length of the text in it. It works if I put .intro p at inline-block, but I would like my p elements all to be displayed underneath each other. Is there a way to do this?
HTML:
<div class="intro">
<p>fjsdqk dhksjfd kjsh kdshjkd</p>
<p>hsdqjkf kjdsh</p>
<p>hdsqkhfj sdhkjf fsjqkfhdks hjs</p>
</div>
CSS:
.intro {
margin-top: 80px;
color: #ffffff;
text-align: center;
}
.intro p {
margin-bottom: 12px;
padding: 6px 12px;
background: #25d6a2;
}
Just add br tag after each p element
<div class="intro">
<p>fjsdqk dhksjfd kjsh kdshjkd</p><br>
<p>hsdqjkf kjdsh</p><br>
<p>hdsqkhfj sdhkjf fsjqkfhdks hjs</p><br>
</div>
Demo
If you don't want to add <br /> in the DOM or for some reason you cannot modify your HTML, you can simulate line break using CSS :after pseudo with content property having an value of \a and white-space set to pre
As far as the explanation goes for \a, its an hexadecimal value for line feed which is equivalent to 10.
p:after {
content:"\a";
white-space: pre;
}
Demo
In a sense, you want to eat your cake and keep it: make the p elements inline elements as far as box formatting is considered (in this case, for the purpose of setting background behind the text only) but block elements in the sense of starting on a fresh line.
There are various methods and tricks, but perhaps the simplest one is to use floating (instead of display: inline-block): float the elements to the left but also clear floating, so that no real floating takes place—you just want the side effect of floating, the effect of making the element just as wide as its content requires:
.intro p {
float: left;
clear: both;
}
In addition, you need to set clear: both on the element after the intro.
I am learning how to code HTML and CSS, and I decided to make my own website in the process.
My question is: how would I align smaller text to a bigger object, for example, links to different pages on my website neatly aligned under my full name with the links flush to the of the beginning and end of my full name?
I know describing it may have been a bit confusing, so here's an image of what I mean:
Any suggestions?
Thanks!
You can approximate the look and design regardless of the header length, but in the end, CSS doesn't offer as precise typographical tools as you'd need and you will have to nudge the percentages one way or another once you know the length of your actual text.
Sample Jsfiddle
HTML:
<div id="container">
<h1>Large Title Here Etc</h1>
<div id="sub">
<span>music</span>
<span>film</span>
<span>web</span>
<span>photo</span>
</div>
</div>
CSS:
body {
text-align: center;
}
#container {
display: inline-block;
}
h1 {
font-size: 2em;
}
#sub {
font-size: 1em;
display: table;
width: 120%;
box-sizing: border-box;
margin: 0 -10%;
}
#sub span {
display: table-cell;
padding: 0 2%;
}
links flush to the beginning and end of my full name
Get out of the habit of thinking this way as you design websites. This will lead to endless headaches and frustrations for you, as it depends on browser rendering (and possibly rendering bugs), the user's font size, the user's font, and loads of other factors you cannot control. Instead of going for 'pixel precision', the idea is simply to make it look as good as you can on most things.
When designing things like this, consider the markup first. What is the structure of what you're actually writing? In your linked image, Full Name looks to me like a header (perhaps h1), while menus like that are normally done as styled unordered lists (ul) these days. Below is an example of how I might make something similar to what is in your image.
Here is the markup:
<div id="container">
<h1>Full Name</h1>
<ul>
<li>music</li>
<li>film</li>
<li>web</li>
<li>photo</li>
</ul>
</div>
and the CSS used, with comments:
#container { border: 1px solid; }
h1 {
margin-bottom: 0;
text-align: center;
}
ul {
margin: 0.5em;
/* remove default padding inserted by browser */
padding-left: 0;
/* no bullets */
list-style-type: none;
/* this works on inline objects, not just text */
text-align: center;
}
li {
/* hybrid of inline and block; obeys text-align */
/* Also note this does not work in IE <9. Workarounds exist. */
display: inline-block;
padding: 3px;
}
And here is the end result: http://jsfiddle.net/3PLgz/1/
I have coded this simple code :Html
<div class="row offset3">
<div class="title">Title1</div>
<div class="title-arrow">
<i class="icon-arrow-left"></i>GoBack
</div>
</div>
css
.title{
margin-top: 20px;
}
.title-arrow{
margin-top: -22px;
margin-left: 50px;
margin-bottom: 14px;
}
my problem is that if i change the Title1 to a bigger one e.g titllleeeeeeeeeeeeee the arrow don't move at right.. Ok i get it its normal behavior! I have to put a property margin in class title. I tried to put an margin-right:10px; but nothing happens..
Just do this:
HTML:
<div class="row offset3">
<div class="title">Titleaa</div>
<span class="title-arrow">
<i class="icon-arrow-left"></i>GoBack
</span>
</div>
CSS
.title{
margin-top: 20px;
display: inline;
}
DEMO
The class title-arrow isnt needed anymore but its there in case you want it.
Its because you set a fixed margin-left: 50px on the arrow. You should wrap it as a span within the the title div.
Check it out: http://bootply.com/83546
You're using two block elements, which are rendered below eachother and are not aware of the flow of their preceding block. That means that if the Title gets longer the arrow does not know about it (and shouldn't) because it's a block-level element. It should not be influenced by it.
You moved the arrow next to the title by using static margin values. Those values don't change and yes, that means that if the title gets longer the arrow will overlap it.
Instead, try to make use of the document flow, either by using inline(-block) elements or a float. Try this for example:
To .title, add:
float: left
Replace the entire rule for .title-arrow with:
.title-arrow {
margin-top: 20px;
line-height: 17px;
}
(these values are the same as that of title, to make sure they are on the same height)
This seems to be a common problem in the Bootstrap community, the process of centering and class with an odd number for the span width, class="span3" for example. I have a .row with three .span3 classes inside it. I realize it would be easier to just use three span4 classes, but I'm not a fan of how large it makes my elements.
I've tried a few things so far:
I've created a custom 15-column grid so I could give a .span3 class before and after the three elements I actually want to use, however when responsive-bootstrap.css kicks in, things act strange because the responsive file deals with a 12-column grid.
I've tried placing everything in a custom .center class which uses the following CSS:
.center {
float: none;
margin: 0 auto;
text-align: center;
}
For what it's worth, everything works when my browser width is between ~980px - ~1199px.
There has to be a simple way to fix this problem, right? I'm not worried about it looking good on older browsers either, this is a personal site. Here is where I'm currently at, working with a 15-column grid:
Here is my JSFiddle
The HTML:
<div class="row">
<div class="center">
<ul class="thumbnails" id="portfolio-links">
<li class="span3"></li>
<li class="span3" id="item1">
</li>
<li class="span3" id="item2">
</li>
<li class="span3" id="item3">
</li>
<li class="span3"></li>
</ul><!--/.thumbnails-->
</div><!--/.center-->
</div><!--/.row-->
The CSS:
#portfolio-links {
display: block;
margin: 0 auto;
float: none;
}
.center {
float: none;
margin: 0 auto;
text-align: center;
}
You just have to make the <div class="center"> with a size of span9 and remove the extra li.
The final result will be: http://jsfiddle.net/AKWqP/
I can't figure out how to do this with CSS. If I just use a <br> tag, it works flawlessly, but I'm trying to avoid doing that for obvious reasons.
Basically, I just want the .feature_desc span to start on a new line, but:
If I make it an inline element, it won't have a line-break.
If I make it a block element, it will expand to fit the entire line, putting each of these icons on its own line, and wasting tons of space on the screen (each .feature_wrapper will be a slightly different size, but none will ever be as wide as the entire screen.)
Example code: This works, but uses a br tag:
<li class='feature_wrapper' id='feature_icon_getstart'>
<span style='display: none;' class='search_keywords'>started</span>
<span class='feature_icon spriteicon_img' id='icon-getstart'><a href='getstarted/index.html' class='overlay_link'></a></span><br/>
<span class='feature_desc'><a href='getstarted/index.html' >Getting Started Wizard</a></span>
</li>
I want to style this with CSS to achieve the same result:
<li class='feature_wrapper' id='feature_icon_getstart'>
<span style='display: none;' class='search_keywords'>started</span>
<span class='feature_icon spriteicon_img' id='icon-getstart'><a href='getstarted/index.html' class='overlay_link'></a></span>
<span class='feature_desc'><a href='getstarted/index.html' >Getting Started Wizard</a></span>
</li>
Any ideas? Or am I going about this the wrong way?
You can give it a property display block; so it will behave like a div and have its own line
CSS:
.feature_desc {
display: block;
....
}
Even though the question is quite fuzzy and the HTML snippet is quite limited, I suppose
.feature_desc {
display: block;
}
.feature_desc:before {
content: "";
display: block;
}
might give you want you want to achieve without the <br/> element. Though it would help to see your CSS applied to these elements.
NOTE. The example above doesn't work in IE7 though.
I think floats may work best for you here, if you dont want the element to occupy the whole line, float it left should work.
.feature_wrapper span {
float: left;
clear: left;
display:inline
}
EDIT: now browsers have better support you can make use of the do inline-block.
.feature_wrapper span {
display:inline-block;
*display:inline; *zoom:1;
}
Depending on the text-align this will appear as through its inline while also acting like a block element.
For the block element not occupy the whole line, set it's width to something small and the white-space:nowrap
label
{
width:10px;
display:block;
white-space:nowrap;
}
Using a flex parent works too.
Setting flex-direction to column will put each child on a new line and setting align-items will make them not take up the whole width.
Here is a small example:
<div class="parent">
<a>some links</a>
<a>that should be on their own lines</a>
<a>but not take up the whole parent width</a>
</div>
.parent {
display: flex;
flex-direction: column;
align-items: flex-start;
}
span::before { content: "\A"; white-space: pre; }
I was running into a similar situation on our WooCommerce site. The "Add to cart" button was right next to a custom product field, and I needed to drop the product field below the button. This is the CSS that ended up doing the trick for me
#product-57310 label[for="wcj_product_input_fields_local_1"] { display: -webkit-box!important; margin-top: 80px; }
where "#product-57310" is the ID of the product in woocommerce, so that it only applies to the specific product page and not every product page, and where "label[for="wcj_product_input_fields_local_1"]" is targeting the first label specifically to get under the "Add to cart" button.
I had a similar issue where I had something like this:
<span>
<input>
<label>
<input>
<label>
...
</span>
I didn't wanna mess with the source html generator (even tho this html is pretty bad). So the way I fixed it is use a display: grid on the top span. Then grid-template-columns: auto auto;
Anyone looking to do something similar, grid is a good solution now (in 2021).
For example, for this particular problem, applying
display: grid; grid-template-columns: auto auto; to li and grid-column: 1 / 3; to last span will do it.
Use two CSS rules
word-break: break-all;
display: list-item;
inside of a CSS selector and body
Note:
If only dealing with text that needs to be put on separate lines.
Try using word-break like so (note stack overflow code automatically does this but I included it to help clarify usage in other environments:
word-break: break-all;
If only dealing with in-line HTML elements like a <span>
Then see this answer as to how to convert non text elements (like an anchor tag) to line separated elements using a display: list-item also on the html tag
Link
How to make text in <a> tag wordwrap
Example (For HTML inline elements like span)
span {
display: list-item;
word-break: break-word;
}
<span>Line 1</span>
<span>Line 2</span>
<span>Line 3</span>
<span>Line 4</span>
<span>Line 5</span>
Example (For Text Content)
function makePerson(name, age) {
// add code here
let person = Object.create({});
person.name = name;
person.age = age;
return person;
}
const person = makePerson('Vicky', 24);
const outputDiv = document.querySelectorAll("body .output");
const keys = Object.keys(person);
outputDiv.forEach((div,key) => {
div.innerHTML = person[keys[key]];
});
body #output{
word-break: break-all;
}
<div>
<div class="output"></div>
<div class="output"></div>
</div>