I want to create a custom loading spinner for my ionic 4 app with a GIF or SVG animation. There is no "content" property to fill with html, so how do I replace the bubbles SVG in this case with a custom SVG or GIF?
It is frustrating that there's no component documentation page for ion-icon, the best thing now is the usage page here which kinda hints at how to do it:
https://ionicons.com/usage
But here's how:
ion-icon {
--background: black; // or an icon, etc
font-size: 12px; // etc
}
You can apply anything there that you normally can with css background properties:
https://www.w3schools.com/css/css_background.asp
let loading = await this.loadingCtrl.create({
spinner: null,
message: '<img src="/assets/loadingGif/loadgif.gif">',\\Your Gif File Path
});
loading.present();
Related
Why is my ion-backdrop + modal shadow styling not working when I open a modal on top of another modal?
PREFACE: This was working fine with V4, but broken on the upgrade to V5. I don’t want to change my page approach, just fix the CSS/whatever is actually causing the issue below.
My app opens a modal page with custom css to make it full screen.
I can then open another normal modal (but not full screen) over the
top. This 2nd modal is missing the ion-backdrop and its border shadow
styling.
I can see the ion-backdrop is definitely in the DOM, but it’s
obviously not showing.
Step1 Fine
enter image description here
Step 2 - broken ion-backdrop:
enter image description here
Showing my custom modal:
async showClipboard() {
const modal = await this._ModalController.create({
component: ClipboardPage,
cssClass: 'custom-round-modal',
componentProps: {
user: this.user
},
showBackdrop: true
});
await modal.present();
}
The CSS:
#media only screen and (min-width: 768px) {
.custom-round-modal {
.modal-wrapper {
border-radius: 15px !important;
-moz-border-radius: 15px !important;
-webkit-border-radius: 15px !important;
.ion-page {
border-radius: 15px !important;
-moz-border-radius: 15px !important;
-webkit-border-radius: 15px !important;
}
}
}
}
First off, I think you pasted the same screenshot twice by mistake. But I'm having the same issue, so I know what you mean.
It looks like Ionic 5 introduced this css for the modals:
.sc-ion-modal-ios-h:first-of-type {
--backdrop-opacity: var(--ion-backdrop-opacity, 0.4);
}
Which means when you show multiple modals at the same time, only the first one will get the backdrop.
A possible workaround is to add the backdrop yourself to your global css using something like this:
ion-modal {
--backdrop-opacity: var(--ion-backdrop-opacity, 0.4);
}
Or use the css class Ionic is using (but note that this one is iOS specific, so you'd likely need to do the same with the Android-equivalent class):
.sc-ion-modal-ios-h {
--backdrop-opacity: var(--ion-backdrop-opacity, 0.4);
}
NOTE: This will likely not look good if you are showing multiple modals on top of each other that are not fullscreen, since you'll be getting multiple backdrops on top of each other (so they'll get increasingly darker). But since your issue is a non-fullscreen modal on top of a fullscreen one, I think it will work in your case.
Hopefully the Ionic team will come up with a more elegant solution to this issue.
Thank you krisloekkegaard for your code, that helped me really out.
I want to add that it will only work if placed in the global sass or css files! You cannot do that from a component's style-file, because the modal will be created outside of it.
The following lines are a bit more precise, because they will activate the backdrop only on the last modal. Even if you have 10 stacked modals, there will be only the backdrop of the first and the backdrop of the last element overlaying each other.
.sc-ion-modal-md-h:last-of-type {
--backdrop-opacity: var(--ion-backdrop-opacity, 0.32);
}
.sc-ion-modal-ios-h:last-of-type {
--backdrop-opacity: var(--ion-backdrop-opacity, 0.32);
}
This is addressed now in the Ionic Documentation.
Please see under 'Customization' section for ion-modal : https://ionicframework.com/docs/api/modal
Add the following CSS to your modal class -
ion-modal.stack-modal {
--box-shadow: 0 28px 48px rgba(0, 0, 0, 0.4);
--backdrop-opacity: var(--ion-backdrop-opacity, 0.32);
}
I solved the issue adding the following css into variables.css file in Ionic v5. Give a chance.
.backdrop-no-scroll {
ion-router-outlet {
background: white;
}
I am new in Ionic. I am stuck on rounded corners for the side drawer menu. Please give me a solution if it works then I accept your answer Anyone here with a solution for this? Thanks in Advance. Here is my code.
.menu-inner {
border-radius: 0px 50px 0px 0px !important;
}
in Inspect element this is perfect work but not work in code
here is screen short
So far, You can not style shadow-root element in the DOM by using CSS. In some cases, the CSS4 helps to style. But in this case, it would not work.
So, You can use JavaScript to style shadow-root element. Here You should create a simple method like menuRadius and call it in initializeApp in the following way.
src/app/app.component.ts
initializeApp() {
this.platform.ready().then(() => {
this.statusBar.styleDefault();
this.splashScreen.hide();
this.menuRadius(); // call menuRadius method
});
}
menuRadius() {
setTimeout(() => {
document.querySelector('ion-menu').shadowRoot.querySelector('.menu-inner').setAttribute('style', 'border-radius:0px 50px 0px 0px');
}, 2000);
}
Please Note Injecting style by using JavaScript only works when shadow-root is open.
You may check this article for more info about shadow-root DOM.
I am using Ionic 2 for developing my App. I want to use my custom icons in my app like we use ionic 2 icons using tag. Eg:
<ion-icon name="my-custom-icon"></ion-icon>
How can i achieve this? Is there any recommended way to doing this?
This is the easiest way I've found, from the forums at https://forum.ionicframework.com/t/anyway-to-custom-the-tabbars-icon-with-my-own-svg-file/46131/36.
In your app.scss file, add the following code:
ion-icon {
&[class*="appname-"] {
// Instead of using the font-based icons
// We're applying SVG masks
mask-size: contain;
mask-position: 50% 50%;
mask-repeat: no-repeat;
background: currentColor;
width: 1em;
height: 1em;
}
// custom icons
&[class*="appname-customicon1"] {
mask-image: url(../assets/img/customicon1.svg);
}
&[class*="appname-customicon2"] {
mask-image: url(../assets/img/customicon2.svg);
}
&[class*="appname-customicon3"] {
mask-image: url(../assets/img/customicon3.svg);
}
}
Then in your templates, you can use the following HTML to create the icon:
<ion-icon name="appname-customicon"></ion-icon>
This is far less complicated than using the font-based methods. As long as you're not adding hundreds of icons you should be okay with this method. However each image is sent as a separate request, where as with the font methods all the images are contained in one file, so it would be a little more efficient.
If you want to use custom fonts in ionic 2+ you can do it with following.
Step 01:
Have/create custom font SVG files using tools such as XD.
Go to awesome online tool https://icomoon.io to generate font icons out of your SVG files. It's free tool and very good, I am using it for a while.
Download your custom font file.
Your file will look like something below.
[class^="icon-"], [class*=" icon-"] {
font-family: 'icomoon' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
}
replace above code with :
[class^="icon-"],
[class*=" icon-"],
[class^="ion-ios-icon"],
[class*="ion-ios-icon"],
[class^="ion-md-icon"],
[class*="ion-md-icon"]{
#extend .ion;
font-family: 'icomoon' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
}
Step 02:
We can use SASS #mixing for repetitive work
#mixin makeIcon($arg, $val) {
.ion-ios-#{$arg}:before ,
.ion-ios-#{$arg}-circle:before ,
.ion-ios-#{$arg}-circle-outline:before ,
.ion-ios-#{$arg}-outline:before ,
.ion-md-#{$arg}:before ,
.ion-md-#{$arg}-circle:before ,
.ion-md-#{$arg}-circle-outline:before ,
.ion-md-#{$arg}-outline:before {
content: $val;
font-size: 26px;
}
}
we can use our sass mixing in our sass file like :
#include makeIcon(icon-new-home, '\e911')
Step 03
Use it like
<ion-tabs class="footer-tabs" [selectedIndex]="mySelectedIndex">
<ion-tab [root]="tab1Root" tabIcon="home"></ion-tab>
<ion-tab [root]="tab2Root" tabIcon="icon-new-home"></ion-tab>
</ion-tabs>
and its even support android ripple effect, which kinda looks cool
[Updated] 30 Nov 2017
#ionic/app-scripts : 3.1.2
Ionic Framework : ionic-angular 3.9.2
For Ionic 3.1.2
You need to add #import "ionicons"; inside your /src/theme/variables.scss file which will fix below error
"[class^="icon-"]" failed to #extend ".ion". The selector ".ion" was not found. Use "#extend .ion !optional"
if the extend should be able to fail.
With the current Ionic 3.3.0 you can use the solution from Anjum, but you have to change
#import "ionic.ionicons";
to
#import "ionicons";
in the src/theme/variables.scss file.
Found this solution at:
https://github.com/yannbf/ionicCustomIconsSample/blob/master/src/theme/variables.scss
Been trying to implement Anjum Nawab shaikh answer on top with the icons sass sheet from icomoon.
I have been able to get it working with version 2.2.2.
In the www/fonts of the project I had added the icomoon files:
icomoon.svg
icomoon.ttf
icomoon.woff
icomoon.eot
icomoon.scss
In icomoon.scss I added the following scss:
#font-face {
font-family: 'icomoon';
src: url('../fonts/icomoon.eot?tclihz');
src: url('../fonts/icomoon.eot?tclihz#iefix') format('embedded-opentype'),
url('../fonts/icomoon.ttf?tclihz') format('truetype'),
url('../fonts/icomoon.woff?tclihz') format('woff'),
url('../fonts/icomoon.svg?tclihz#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
[class^="icon-"],
[class*=" icon-"],
[class^="ion-ios-icon"],
[class*="ion-ios-icon"],
[class^="ion-md-icon"],
[class*="ion-md-icon"]{
/* Didn't feel the need to #extend since this just adds to already existing .ion
code which I believe is replaced to just ion-icon tag selector in
www/assets/fonts/ionicons.scss */
font-family: "Ionicons", "icomoon" !important; //So just add this
}
//Mixin
#mixin makeIcon($arg, $val) {
.ion-ios-#{$arg}:before ,
.ion-ios-#{$arg}-circle:before ,
.ion-ios-#{$arg}-circle-outline:before ,
.ion-ios-#{$arg}-outline:before ,
.ion-md-#{$arg}:before ,
.ion-md-#{$arg}-circle:before ,
.ion-md-#{$arg}-circle-outline:before ,
.ion-md-#{$arg}-outline:before {
//important to overwrite ionic icons with your own icons
content: $val !important;
font-size: 26px;
}
}
//Adding Icons
#include makeIcon(email, '\e900');
...
Then I did an import to the variables.scss
#import "../www/fonts/icomoon";
Now we can add this to the html template:
<ion-icon name="email"></ion-icon>
Before starting : make sure that you have every svg file you need.
Now just go here : http://fontello.com/
That tool will generate your icon font and the CSS needed with. It is pretty intuitive, just use it, download, and copy your font wherever you want in your www folder but keep the same file structure. To finish, just integrate your CSS file in your index.html file and you're done!
I hope it will solve your issue! ;-)
According to ionic team:
Hey there!
Right now it's limited to using ionicons, since underneath it's rendering an ion-icon, and thats handling the platform differences. You could open an issue and we could discuss adding this feature there
You can see all answers in here:
https://forum.ionicframework.com/t/anyway-to-custom-the-tabbars-icon-with-my-own-svg-file/46131/16
I also find this:
https://www.npmjs.com/package/ionic2-custom-icons ,
but do not seems a clever solution (I prefer to wait for a solution of Ionic team).
The best scenario for this is use old way, by creating a class on a scss file.
For add custom icons I use in my scss file:
.ion-ios-MYICON:before,
.ion-ios-MYICON-circle:before,
.ion-ios-MYICON-circle-outline:before,
.ion-ios-MYICON-outline:before,
.ion-md-MYICON:before,
.ion-md-MYICON-circle:before,
.ion-md-MYICON-circle-outline:before,
.ion-md-MYICON-outline:before {
#extend .ion;
}
.ion-ios-MYICON:before,
.ion-ios-MYICON-outline:before,
.ion-md-MYICON:before,
.ion-md-MYICON-outline:before {
content: 'your-custom-image';
}
Then in your HTML code:
<ion-icon name="MYICON"></ion-icon>
I think this step-by-step by GerritErpenstein is very intuitive, it works pretty good for me. My Ionic version is 2.2.2. Literally, you use a sentence like this and it's done:
<custom-icon set="star" name="iconostar"></custom-icon>
https://github.com/GerritErpenstein/ionic2-custom-icons
Create Icon
ion-icon {
&[class*="custom-"] {
mask-size: contain;
mask-position: 50% 50%;
mask-repeat: no-repeat;
background: currentColor;
width: 0.8em;
height: 0.8em;
}
&[class*="custom-rupee"] {
color: yellow;
mask-image: url(../../assets/Images/rupee.svg);
}
&[class*="custom-ballon"] {
mask-image: url(../../assets/ballon.svg);
}
&[class*="custom-mouse"] {
mask-image: url(../../assets/mouse.svg);
}
}
And to use them
<ion-icon name="custom-rupee"></ion-icon>
<ion-icon name="custom-mouse"></ion-icon>
<ion-icon name="custom-ballon"></ion-icon>
If ionic way is not working for you, you can work with the angular way. Use this package: https://www.npmjs.com/package/angular-svg-icon.
Sample Code for ionic usage:
<svg-icon src="/assets/icons/activity.svg"></svg-icon>
Following is the recommended way to display external svg icons using ion-icon:
To use a custom SVG, provide its url in the src attribute to request the external SVG file. The src attribute works the same as in that the url must be accessible from the webpage that's making a request for the image. Additionally, the external file can only be a valid svg and does not allow scripts or events within the svg element.
<ion-icon src="assets/icons/custom_icon.svg"></ion-icon>
Reference: https://ionic.io/ionicons/usage
I am using gwt for showing a dynamic image inside a td and the image is coming from a imagebundle but its showing the whole big image, which gwt makes during compilation, inside that td rather than showing specific part from that big image. I don't know what I am missing here... The problem is the image will be added and selected dynamically and I can't define a css everytime I add an image. If anyone of you can help me regarding it. Here is my code
My table cell is defined inside the UiBinder something like....
<ui:style>
.colourPickerCell {
background-repeat:no-repeat;
}
</ui:style>
<tr>
<td class="{style.colourPickerCell}" ui:field="colourPreviewSlot" rowspan="3" width="50%"></td>
</tr>
Function inside the presenter class:
public void newColorSelected(Image patternImage) {
Style patternImageStyle = patternImage.getElement().getStyle();
Style style = getColourPreviewSlot().getStyle();
style.setWidth(patternImage.getWidth(), Unit.PX);
style.setBackgroundImage(patternImageStyle.getBackgroundImage());
style.setLeft(-patternImage.getOriginLeft(), Unit.PX);
style.setTop(-patternImage.getOriginTop(), Unit.PX);
style.setHeight(patternImage.getHeight(), Unit.PX);
}
When I debug my code I get the html for patternImage object as:
<img id="..." style="backgrond:url(....) no-repeat -149px 12px;"/>
Best regards,
If you are using this image as a background sprite, it think you have to use background-position css property to "move" your image "behind" the td.
"left" and "top" properties are relative to the element you set the style on, not its underlying background image.
I want to hide the big play button that appears by default on the <video> element
Is it possible?
I don't have any iOS device handy to test, but perhaps try this:
video::-webkit-media-controls {
display:none !important;
}
It seems Apple has changed the shadow-dom again.
In order to hide the play button control you must use the following CSS:
/* This used to work for the parent element of button divs */
/* But it does not work with newer browsers, the below doesn't hide the play button parent div */
*::-webkit-media-controls-panel {
display: none!important;
-webkit-appearance: none;
}
/* Old shadow dom for play button */
*::-webkit-media-controls-play-button {
display: none!important;
-webkit-appearance: none;
}
/* New shadow dom for play button */
/* This one works! */
*::-webkit-media-controls-start-playback-button {
display: none!important;
-webkit-appearance: none;
}
A look at the shadow DOM in Safari iOS tells me that what you want (hidding only the big central play button) is:
video::-webkit-media-controls-start-playback-button {
display: none !important;
}
The answer from Ian hides everything including text tracks (closed captions ...)
Newer iOS versions display such play button when the device is in "Low power mode".
In the video source file you can simply change
controls= "false"
For the Safari CSS, which the native browser on ios, you can also try this hacky trick
.custom-video-controls {
z-index: 2147483647;
}
Here's a link to a details discussion on managing/hiding controls on HTML 5 video
http://css-tricks.com/custom-controls-in-html5-video-full-screen/
UPDATE OCTOBER 2021
All answers are outdated for iOS 13, 14, and 15. It appears because iOS low power mode prevents autoplay on all videos in the browser by default (to save power).
The best way to remove the annoying play button is to remove the autoplay tag on any video element and start playing the video when there is any user interaction.
React example below:
<video ref={playerRef} playsInline >
let playVideo = (event) => {
if (playerRef.current) {
playerRef.current.play()
}
}
Sidenote: the play button is hidden in a shadow dom that I am unable to figure out how to hide with external CSS modifications or even JS. If anyone has any ideas on how to hide a shadow dom element then that would be a better solution.
Based on Ian's answer
video::-webkit-media-controls {
opacity: 0;
}
This will hide all controls. Good for background videos that won't autoplay.
Today #2017 in iOS 10 this works:
.video-background::-webkit-media-controls-panel,
.video-background::-webkit-media-controls-start-playback-button {
display: none !important;
}
For webapps.
Works iOS 10.3 iPhone7 & Safari 10.1 on Mac as well. Thx to previous contributors.
I had also the issue that the element does not contain any "control" attribute at all.
'<style type="text/css">'+
'*::-webkit-media-controls-panel {'+
' display: none!important;'+
' -webkit-appearance: none;'+
' }'+
/* Old shadow dom for play button */
'*::--webkit-media-controls-play-button {'+
'display: none!important;'+
'-webkit-appearance: none;'+
'}'+
/* New shadow dom for play button */
/* This one works */
'*::-webkit-media-controls-start-playback-button {'+
'display: none!important;'+
' -webkit-appearance: none;'+
'}'+
+'</style>'
Try this:
video {
&::-webkit-media-controls {
display:none !important;
}
&::-webkit-media-controls-start-playback-button {
display: none!important;
-webkit-appearance: none;
}
}
Update:
IOS 13.*
video::slotted::-webkit-media-controls-container{
display:none !important;
visibility: hidden!important;
opacity: 0 !important;
-webkit-appearance: none !important;
}
IOS 14
changed selector to
:host::shadow::-webkit-media-controls-container{/* hide the element */}
helpful resource:
html5rocks shadow dom 201
As of 20 Oct 2022,
My solution was to remove autoplay from the video element and use HTMLMediaElement.play() on page load. The promise returned from play() will catch any issues with playing the video, else the video will play as usual. My implementation in React looks like this:
useEffect(() => {
ref &&
ref.current
.play()
.then(() => {})
.catch((err) => {
// Video couldn't play, low power play button showing.
});
}, []);
This should be a relief from having to deal with the inconsistent Shadow DOM properties.
Resources:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play
You can't remove the play button. This video placeholder always appears as the doc says :
iPhone Video PlaceHolder. But maybe you can detect you're on an iphone and display an image with a link to your video instead of the video tag.
<img src="yourposter.png"/>
The video will be launched in a player just as a video tag.
According to this answer, in Google Chrome we can hide the big play button like this:
video::-webkit-media-controls-overlay-play-button {
display: none;
}
That might be useful if you want to hide it on Android as well as on iOS.
video::-webkit-media-controls { display:none !important; }
Didn't work for me on iOS, but
*::-webkit-media-controls-panel {
display: none!important;
-webkit-appearance: none;
}
/* Old shadow dom for play button */
*::--webkit-media-controls-play-button {
display: none!important;
-webkit-appearance: none;
}
/* New shadow dom for play button */
/* This one works */
*::-webkit-media-controls-start-playback-button {
display: none!important;
-webkit-appearance: none;
}
Worked perfect!
Yes you can do this! The trick is to "hide" the video controls, by not adding the "controls" attribute to your video tag. Then you let it be dynamically added a few seconds after the video starts to play, by appending the "controls" property to the tag using Javascript. Simply set the value to "controls" and it will dynamically appear in the DOM... as if you had added the controls to your video tag's HTML. Adjust the timer as needed.
<video id="some-video-id" src="some-video-url" poster="some-thumbnail-url" />
Start the Video
<script type="text/javascript">
var oVideoTag = document.getElementById('some-video-id');
var oLink = document.getElementById('startVideoLink');
if (oLink && oVideoTag) {
oLink.addEventListener('click',function(e) {
oVideoTag.play();
setTimeout(function() {
oVideoTag.controls = 'controls';
},2500);
},false);
}
</script>